2

編集:混乱を解消するために、実際には and を使用していませMaleFemale。より良い例は、親クラスAnimalとサブクラスCatDogです。
私はOOPの初心者ですが、これまでのところかなりよく理解しています。しかし、私ができる方法を見つけることができることが1つあります。
まず、ユーザーに基づいて新しいオブジェクトを作成します。ユーザーは(この例では)男性でも女性でもかまいませんが、データベースにチェックインしないと、男性かどうかを確認できません。次に、性別のサブクラスを持つ新しいユーザー オブジェクトを作成する必要があります。
たとえば、これが私の現在の(乱雑な)コードです。

$user = new Person();
$userType = $user->GetUserType($userid);
if ($userType == 'Male') {
    $user = new Male($userid);
} else {
    $user = new Female($userid);
}

新しいオブジェクトを作成したい場合は、毎回これを行う必要がありますが、これはやりたくないことです。
これを視野に入れるのに役立つもう少しのコードを次に示します。

class Person {
function GetUserType($userid) {
        $db = mysqlConnect();
        $stmt = $db->stmt_init();
        // Get the players information
        $stmt->prepare("SELECT user_type FROM user_information WHERE user_id = ?");
        $stmt->bind_param('i', $userid);
        $stmt->execute();
        $stmt->bind_result($userType);
        $stmt->fetch();
        $stmt->close();
        $db->close();
        return $userType;
    }
}
class Male extends Person {
    // Male based things here
}
class Female extends Person {
    // Female based things here
}

そこで、__constructクラスのPerson中で、ユーザーの性別をチェックし、適切なサブクラスを設定したいと思います。

4

2 に答える 2

2

そこで、__constructPerson クラスの で、ユーザーの性別をチェックし、適切なサブクラスを設定したいと思います。

すでに他の場所で述べたように、ctors は返されないため、それを行うことはできません。とにかく、ctors はデータベースにクエリを実行するべきではありませDataMapperまたはRepositoryを介して正しいサブタイプをすぐに作成できない/作成したくない場合は、 State Patternを使用できます。

内部状態が変化したときにオブジェクトの動作を変更できるようにします。オブジェクトはそのクラスを変更するように見えます。

これは、Gang Of Four の本の行動パターンの 1 つです。ここでのキーワードは、明らかに行動です。状態パターンは、サブタイプ (猫、犬) の変化そのものではなく、それらの動作の違いに関するものです。したがって、あなたの質問に対する私のコメント。

例:

interface GenderBehavior
{
    public function someBehavior();
    // can add more methods here
}

class FemalePersonBehavior implements GenderBehavior
{
    public function someBehavior()
    {
        // female specific behavior
    }
}

class MalePersonBehavior implements GenderBehavior
{
    public function someBehavior()
    {
        // male specific behavior
    }
}

class UnknownGenderBehavior implements GenderBehavior
{
    public function someBehavior()
    {
        // either implement a neutral behavior or
        throw new LogicException('Unknown Gender set');
    }
}

これらのインスタンスを作成するには、Factoryを追加します

class GenderBehaviorFactory
{
    public static function create($sex = null)
    {
        switch ($sex) {
           case 'male':
               return new MalePersonBehavior;
           case 'female':
               return new FemalePersonBehavior;
           default:
               return UnknownGenderBehavior;
        }
    }
}

GenderBehavior次に、インターフェイスをクラスに追加Personし、インターフェイス メソッドへのすべてのアクセスを Behavior インスタンスにトンネリングします。

class Person implements GenderBehavior
{
    private $behavior;

    public function __construct()
    {
        $this->behavior = GenderBehaviorFactory::create();
    }

    public function changeGender($sex)
    {
        $this->behavior = GenderBehaviorFactory::create($sex);
    }

    public function someBehavior()
    {
        $this->behavior->someBehavior();
    }
}

Person を初めて作成すると、 でインスタンス化され、UnknownGenderBehaviorを呼び出そうとするとsomeBehavior、例外が発生します。changeGendermale または female のいずれかを引数として呼び出すと、適切なGenderBehaviorが作成され、 に設定されPersonます。そして、あなたは呼び出すことができますsomeBehavior

于 2012-05-12T18:33:00.483 に答える
0

コンストラクターから何を返すかを選択することはできませんが、階層をそのまま (Person性別が不明でMaleありFemale、既知である)、次のパターンのようなものを使用できます。

public class Person {
    public function ensureHasGender() {
        if ($this instanceof Male || $this instanceof Female) {
            return $this;
        }

        // now construct a Male or Female object from $this and return it
        $userType = $user->GetUserType($this->userid);
        return new $userType($this->userid);
    }
}

したがって$user->ensureHasGender()、何度でも呼び出すことができ、性別固有のインスタンスのみが最初に構築されます。

しかし、この戦略には疑問があると思います。Maleセパレートクラスとクラスを持つことで何を得ることができますFemaleか? 彼らの行動が大きく異なる場合、これは正当化される可能性がありますが、そうは思えません。おそらく、遅延読み込みと適切な条件を使用して、クラス内で問題を内部的に処理する方がよいでしょう。

于 2012-05-12T17:23:38.033 に答える