I'm writing a package that is designed to provide a convenient way to inspect the schema for a database.  The goal is that I can use it for generator code to suit the schema.  The complete code can be found at https://github.com/courtney-miles/schnoop.For example, I have classes for IntType, VarCharType, BlobType, etc.  And I need to be able to construct these types from the results of the query, SHOW FULL COLUMNS FROM tbl;These data type objects conform to a common interface, DataTypeInterface.<?phpinterface DataTypeInterface{    /**     * Get the name of the type.     * @return string     */    public function getName();    /**     * Indicates if a default value can be used with this type in a column.     * @return bool     */    public function allowDefault();    /**     * Cast a value from MySQL to a suitable PHP type.     * @param mixed $value     * @return mixed     */    public function cast($value);}Additional interfaces are combined to reflect the unique properties of the data types.  For example, this is the interface for used by all integer types.<?phpinterface IntTypeInterface extends DataTypeInterface{    public function getDisplayWidth();    public function isSigned();    public function getMinRange();    public function getMaxRange();}(To be more correct, the IntTypeInterface actually extends other interfaces that specify these properties because there is an overlap with Floating Point Types.  If you are interested in precisely all the interfaces involved, refer to https://github.com/courtney-miles/schnoop/blob/master/src/Schema/MySQL/DataType/IntTypeInterface.php)So this is my current factory method which is obviously quite ugly.<?phpclass Factory{    // ...    /**     * @param string $dataTypeString Data type string as reported by MySQL when executing SHOW FULL COLUMNS FROM table;     * @param null $collation     */    public function createDataType($dataTypeString, $collation = null)    {        $dataType = null;        if (preg_match('/^(tiny|small|medium|big)?int(eger)?\((\d+)\)( unsigned)?/i', $dataTypeString, $matches)) {            $displayWidth = $matches[3];            $signed = empty($matches[4]);            switch (strtolower($matches[1])) {                case 'tiny':                    $dataType = new TinyIntType($displayWidth, $signed);                    break;                case 'small':                    $dataType = new SmallIntType($displayWidth, $signed);                    break;                case 'medium':                    $dataType = new MediumIntType($displayWidth, $signed);                    break;                case 'big':                    $dataType = new BigIntType($displayWidth, $signed);                    break;                default:                    $dataType = new IntType($displayWidth, $signed);                    break;            }        } elseif (preg_match('/^(decimal|float|double)\((\d+),(\d+)\)( unsigned)?/i', $dataTypeString, $matches)) {            $precision = $matches[2];            $scale = $matches[3];            $signed = empty($matches[4]);            switch (strtolower($matches[1])) {                case 'decimal':                    $dataType = new DecimalType($precision, $scale, $signed);                    break;                case 'double':                    $dataType = new DoubleType($precision, $scale, $signed);                    break;                case 'float':                    $dataType = new FloatType($precision, $scale, $signed);            }        } elseif (preg_match('/^(var)?binary\((\d+)\)$/i', $dataTypeString, $matches)) {            $isVarBinary = !empty($matches[1]);            $length = $matches[2];            if (strtolower($isVarBinary)) {                $dataType = new VarBinaryType($length);            } else {                $dataType = new BinaryType($length);            }        } elseif (preg_match('/^bit\((\d+)\)$/i', $dataTypeString, $matches)) {            $dataType = new BitType($matches[1]);        } else {            $characterSet = !empty($collation) ? $this->getCharacterSet($collation) : null;            if (preg_match('/^(var)?char\((\d+)\)$/i', $dataTypeString, $matches)) {                $isVarChar = !empty($matches[1]);                $length = $matches[2];                if ($isVarChar) {                    $dataType = new VarCharType($length, $characterSet, $collation);                } else {                    $dataType = new CharType($length, $characterSet, $collation);                }            } elseif (preg_match(/(set|enum)(\('.+'\))/i, $dataTypeString, $matches)) {                $options = $this->parseOptions($matches[2]);                switch (strtolower($matches[1])) {                    case 'set':                        $dataType = new SetType($options, $characterSet, $collation);                        break;                    case 'enum':                        $dataType = new EnumType($options, $characterSet, $collation);                        break;                }            } else {                switch (strtolower($dataTypeString)) {                    case 'text':                        $dataType = new TextType($characterSet, $collation);                        break;                    case 'tinytext':                        $dataType = new TinyTextType($characterSet, $collation);                        break;                    case 'mediumtext':                        $dataType = new MediumTextType($characterSet, $collation);                        break;                    case 'longtext':                        $dataType = new LongTextType($characterSet, $collation);                        break;                    case 'blob':                        $dataType = new BlobType();                        break;                    case 'tinyblob':                        $dataType = new TinyBlobType();                        break;                    case 'mediumblob':                        $dataType = new MediumBlobType();                        break;                    case 'longblob':                        $dataType = new LongBlobType();                        break;                }            }        }        return $dataType;    }}I am unsure of the most ideal pattern to clean this up.  My current thoughts are:Use something like the Chain Of Responsibility pattern, where I have a factory per data type, and each will decide if it can handle the data type string, and if it can't it will be passed onto the next factory.Have a factory per data type, and a super factory that would examine the data type string to determine the correct data type factory to handle the string.All examples of Factory patterns that I see are where the different objects all have the exact same constructor arguments. So I'm not sure of the the most sensible pattern to solve when the different objects have different constructor arguments.Note, I originally posted this at on Stackoverflow at https://stackoverflow.com/questions/38339366/how-to-employ-the-factory-pattern-where-the-constructor-arguments-vary
Factory method that constructs objects that represents MySQL data types from query results
php;design patterns;factory method