我正在编写一个包,我需要让PHP对象代表MySQL数据类型。
例如,我有IntType
,VarCharType
,BlobType
等课程。
每个都有不同的构造函数参数。即IntType
有一个已签名的属性,VarChar
有整理等等。
我需要从数据库构建这些类型的源代码。所以我可能有" INT(10)UNSIGNED"," VARCHAR(255)"和" BLOB"。
所以目前我有一个检查和拆分这些字符串的方法,它使用大量的IF和SWITCH语句来确定需要构造哪个类。
我知道这很难看,但我不确定最好的方法。 Factory模式的所有教科书示例都基于生成具有相同构造函数参数的类。
目前我有两个想法可以解决这个问题:
因为我没有看到太多关于此的理论,所以我不太了解最理想的方向。
以下是令人讨厌的代码,以显示它是多么丑陋......
<?php
class 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;
}
}
更新:已在https://codereview.stackexchange.com/questions/134709/a-pattern-to-clean-up-this-factory-method
重新发布