防止类实例化独立,从工厂启用

时间:2014-12-13 15:16:26

标签: php

我想禁用一个由new运算符实例化的类,但我们假设一个getObject方法创建并返回它的一个实例。它可行吗?

2 个答案:

答案 0 :(得分:4)

class C
{
    protected function __construct()
    {
    }

    public static function getObject()
    {
        return new self();
    }
}

更新:

上面的代码满足要求:无法使用new实例化类,需要使用工厂方法getObject()来创建对象。但是,OP没有说明他们需要这样一个结构的原因。

出现这种设计有几个原因;其中之一就是当C类型的对象的创建需要通过一些初始化来完成时,无论出于何种原因,都无法在类的构造函数中完成。

这种构造类C对象的方法的另一个原因是Singleton设计模式;实际上这是一种“反模式”,但这是另一种讨论;为了实现Singleton,类C应如下所示:

    class C    
    {
        private static $instance = NULL;

        protected function __construct()
        {
        }

        public static function getObject()
        {
            if (! isset(self::$instance)) {
                self::$instance = new self();
            }
            return self::$instance;
        }
    }

Singleton与否,因为方法getObject()是静态的,所以测试框架不能对其进行存根或模拟,并且必须使用其原始实现。更多,因为它是创建类C的对象的唯一方法,所以使用此类的其他类不能单独测试。

总而言之,即使是可以施工,也不建议使用。使用语言机制强制创建类C的对象使得该类成为测试使用它的其他类的麻烦。

如果由于复杂的初始化而需要通过某种方法创建类C的对象,则更好的方法是使用Builder设计模式。使它成为另一个类(“构建器”)的非静态方法,并指示程序员(使用类文档)不使用C直接创建类new的对象。这样它不会影响其他类的可测试性。

答案 1 :(得分:3)

  

我想禁用由new运算符

实例化的类

一种常见的方法是将构造函数私有化。

class Example {
    private function __construct() {
    }
}

以下情况会导致致命错误。

$object = new Example();

虽然这会奏效,但我鼓励您和未来的读者审核Design Patterns in PHP