2

编辑:为了消除一些混乱,我实际上并没有使用Maleand Female。一个更好的例子是父类Animal和子类CatDog.
我对 OOP 有点陌生,但到目前为止我已经很好地掌握了它。但是,有一件事我完全可以找到一种方法。
首先,我创建了一个基于用户的新对象。用户可以是(对于这个例子)男性或女性,但如果不检查数据库,我无法检查他们是否是。然后我需要用他们的性别的子类创建一个新的用户对象。
例如,这是我当前的(凌乱的)代码:

$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 都不应该查询数据库,因为那样会起作用。如果您不能/不想立即通过DataMapperRepository创建正确的子类型,则可以使用State Pattern

允许对象在其内部状态发生变化时改变其行为。该对象将出现更改其类。

这是《四人帮》书中的行为模式之一。显然,这里的关键字是行为。状态模式不是关于不同的子类型(猫、狗)本身,而是关于它们所具有的行为的差异。因此,我对您的问题发表了评论。

例子:

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');
    }
}

要创建这些实例,您添加一个工厂

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 时,它将使用 an 实例化,UnknownGenderBehavior如果您尝试调用someBehavior,它将引发异常。当您changeGender使用男性或女性作为参数调用时,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()多次,并且它只会在第一次构建一个特定于性别的实例。

但是,我认为这种策略是有问题的。你能从分开MaleFemale上课中得到什么?如果他们的行为如此不同,那么这可能是合理的,但这听起来不太可能。也许使用延迟加载和适当的条件在类内部处理问题会更好。

于 2012-05-12T17:23:38.033 回答