5

在我们 MVC 系统中所有模型的基类中,我创建了一个工厂方法 BaseCLass::getNew(),它在通过 SomeChildClass::getNew() 调用时返回所请求子类的实例。

现在,我正在寻找一种方法来强制程序员使用这个工厂。即,我通常希望直接创建任何类,如下所示:

 new SomeChildClass

创建时会抛出异常,只有工厂创建的类才能使用。

任何想法如何实现?

我们的代码是用 PHP 编写的,但即使您使用不同的语言思考,您的想法也很有可能是有价值的。

编辑:我不能将我的构造函数设为私有,因为我继承的类中的框架构造函数是公共的,而 php 不允许我这样做。

4

4 回答 4

2

通过制作子类的构造函数protected。父类将有权访问子类的所有受保护方法。任何直接创建孩子的尝试(即:)new child都会导致致命错误。

<?php

class factory
{

    static public function create()
    {
        return new child;
    }

}

class child extends factory
{

    protected function __construct()
    {
        echo 'Ok';
    }

}

$c = factory::create(); // Ok
$c2 = new child; // fatal error

?>

虽然这个方法不会让你抛出异常:(

如果绝对必要,只会想到 debug_backtrace()函数(除了对子本身使用单例,或者使用和传递由工厂生成并由子验证的 GUID 的强制对象池模式)。在子构造函数中,查看第二个数组值以确保“function”===“create”和“class”===“factory。如果不匹配则抛出异常。我最初没有建议这个,只是因为我怀疑使用debug_backtrace可能会影响性能。

于 2011-03-27T03:15:04.400 回答
1

通过使类具有私有构造函数

更新 - 涵盖您声明的要求的解决方案

class Base {
    private static $constructorToken = null;

    protected static function getConstructorToken() {
        if (self::$constructorToken === null) {
            self::$constructorToken = new stdClass;
        }

        return self::$constructorToken;
    }
}

class Derived extends Base {
    public function __construct($token) {
        if ($token !== parent::getConstructorToken()) {
            die ("Attempted to construct manually");
        }
    }

    public static function makeMeOne() {
        return new Derived(parent::getConstructorToken());
    }
}

stdClass该解决方案通过在只有派生类可以访问的基类上存储“魔术密码”对象来利用对象相等规则。你可以调整它的味道。

我不会像这个想法那样称它为可怕debug_backtrace,但我仍然觉得事情应该以不同的方式做。

于 2011-03-27T02:35:04.637 回答
0

将类的构造函数声明为私有,并且只能从类自己的方法中调用,例如getNew().

于 2011-03-27T02:34:37.780 回答
0

有几种方法可以实现它

  • 使父类私有使用魔法
  • 用户魔术函数__autoload;检查类的类型并通过错误和不允许的消息

http://php.net/manual/en/function.is-a.php

于 2011-03-27T03:02:09.570 回答