Является ли мой factory анти-шаблон?
Я видел этот код по другому вопросу - второй ответ link, и первым комментарием было то, что он является статическим factory анти-шаблоном и что он нарушает SRP
class User {
public static function create($userid) {
// get user from the database
// set $isPartner to true or false
// set $isClient to true or false
// set $isModerator to true or false
if ($isPartner) {
return new Partner($userid);
} elseif ($isClient) {
return new Client($userid);
} elseif ($isModerator) {
return new Moderator($userid);
} else {
return new User($userid);
}
}
}
$person = User::create($userid);
Теперь я могу понять, почему он нарушает SRP - потому что он связан с подключением к базе данных, а также с созданием нового класса, но кроме того, я не уверен, понимаю ли я, почему это анти-шаблон.
Я хотел написать немного кода, который казался очень похожим на это, поэтому мне теперь интересно, следует ли его избегать, это мой код (в псевдокоде):
class DatabaseClass()
{
...deals with getting a result from the database...
}
abstract class User()
{
...base class for all users...
}
class AdminUser extends User(){}
class StaffUser extends User(){}
class BasicUser extends User(){}
class UserFactory()
{
function createUser($privilege)
{
if($privilege=="high")
return new AdminUser($privilege);
else if($privilege=="med")
return new StaffUser($privilege);
else
return new BasicUser($privilege);
}
$db=new DatabaseClass($username,$password);
$result=$db->getUser();
$userfactory=new UserFactory();
$user=$userfactory->createUser($result);
Теперь на данный момент я не использую статический метод, но мой oop все равно будет рассматриваться как анти-шаблон?
Тем более, что на самом деле я не вижу никакой разницы в том, чтобы делать что-то вроде этого, и это примерно одно и то же:
$result=DatabaseClass::getUser($username,$password);
$user=UserFactory::createUser($result);
Ответы
Ответ 1
Нет, это не анти-шаблон. Лично я воспринимаю термин "анти-шаблон" с зерном соли всякий раз, когда вижу это. Это слишком легко подбрасывается людьми, которые не любят ваш код, но не могут действительно объяснить, почему.
Проблема со статическим factory заключается в том, что любой класс, который использует factory, должен явно зависеть от него. Это нарушает принцип, согласно которому мы должны зависеть от абстракций, а не от конкреций ( "D" в SOLID). Это делает код с помощью factory более сложным для повторного использования и unit test. Но имейте в виду, что этот подход также имеет свои преимущества. Это легче писать и легче понять.
Ваш код эквивалентен статическому методу factory. Проблема в обоих случаях заключается в том, что вызывающий должен знать конкретный класс factory.
Ответ 2
Ваш factory не является проблемой, является ли связь с db, я думаю.
Кроме этого, вы хорошо используете метод factory.
После просмотра редактирования его наилучшим образом отделите доступ к данным из factory.
Это не столько "анти-шаблон", сколько плохая идея с точки зрения обслуживания.
Я бы все-таки был в порядке (не так хорошо, но все еще хорошо), если у вас был код доступа к данным внутри factory, если этот код был в отдельном классе (который повторно используется в приложении для доступа к данным) и вы просто называете это, чтобы получить то, что вам нужно. В этом случае это будет комбинация двух шаблонов: factory и фасад.
То, что я действительно заплатил, заключается в том, чтобы выяснить, не изменится ли информация во время сеанса, если это так просто пойти один раз в db, сохранить результаты. Если вы только однажды создадите Пользователь (или производные классы), сделайте damm уверенным, что вы делаете это только один раз.
То, что я думаю, более важно, чтобы слепое соблюдение шаблонов.
Ответ 3
PHP имеет функциональные возможности создания динамического класса, где имя класса, которое должно быть создано, может быть переменной. Следующий код работает нормально:
$classname='User';
$Object=new $classname; //instantiates new User()
Этот код создает экземпляр класса, имя которого хранится в переменной $classname.
Ответ 4
Я не так хорошо с шаблоном Factory, однако, если вы хотите получить какую-то выгоду, он может абстрагировать создание, основанное на вариации настойчивости, например. если он адаптирует базу данных для пользователей или нет.
class DatabaseUserFactory implements UserFactory
{
private $dbClass;
function __construct(DatabaseClass $dbClass)
{
$this->dbClass = $dbClass;
}
/**
* @return user
*/
function createUser()
{
$result = $db->getUser();
return $this->createUserByPrivilege($result->getPrivilege());
}
private function createUserByPrivilege($privilege)
{
if ($privilege == "high")
return new AdminUser($privilege);
else if ($privilege == "med")
return new StaffUser($privilege);
else
return new BasicUser($privilege);
}
}
$db = new DatabaseClass($username, $password);
$userfactory = new DatabaseUserFactory($db);
// ...
$user = $userfactory->createUser();