14

別の質問でこのコードを見ました-2番目の回答リンクと最初のコメントは、それが静的な工場のアンチパターンであり、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);
4

4 に答える 4

10

いいえ、それはアンチパターンではありません。個人的には、「アンチパターン」という言葉を目にするたびに、塩の粒と一緒に受け取ります。あなたのコードが好きではないが、その理由を明確に説明できない人々によって、あまりにも簡単に放り出されてしまいます。

静的ファクトリの問題は、ファクトリを使用するすべてのクラスが明示的に依存する必要があることです。これは、具象ではなく抽象化に依存すべきであるという原則 (SOLID の「D」) に違反しています。これにより、ファクトリを使用するコードの再利用と単体テストが難しくなります。ただし、このアプローチにはメリットもあることに注意してください。その方が書きやすいし、理解しやすい。

コードは静的ファクトリ メソッドと同等です。どちらの場合も問題は、呼び出し元がファクトリの具体的なクラスを知っている必要があることです。

于 2013-01-24T15:43:36.627 に答える
0

PHP には動的クラス インスタンス化の機能があり、インスタンス化する必要があるクラス名は変数にすることができます。次のコードは正常に動作します。

$classname='User';

$Object=new $classname; //instantiates new User()

このコードは、名前が $classname 変数に格納されているクラスをインスタンス化します。

于 2014-09-14T12:50:23.433 に答える
-2

私は 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();
于 2014-05-10T12:32:26.100 に答える