Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/228.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 单例类的构造_Php_Constructor_Singleton - Fatal编程技术网

Php 单例类的构造

Php 单例类的构造,php,constructor,singleton,Php,Constructor,Singleton,这是一个道德问题 我计划在我的新项目中使用几个经理类,它们将在整个项目中执行各种任务。这些类是单例类,但需要基于参数进行构造 至于何时/何地必须进行这种建设,我有复杂的感觉。到目前为止,我有以下选择: 选项A 只需将这些参数传递给getInstance方法,同时使用默认的null值,就很容易了。在第一次调用时,将使用这些参数,任何其他调用都会完全忽略它们 虽然这样做有效,但由于以下原因,这样做感觉相当不合逻辑: 它使文档不清晰。getInstance'第一个参数的类型必须是Collection

这是一个道德问题

我计划在我的新项目中使用几个经理类,它们将在整个项目中执行各种任务。这些类是单例类,但需要基于参数进行构造

至于何时/何地必须进行这种建设,我有复杂的感觉。到目前为止,我有以下选择:

选项A

只需将这些参数传递给
getInstance
方法,同时使用默认的
null
值,就很容易了。在第一次调用时,将使用这些参数,任何其他调用都会完全忽略它们

虽然这样做有效,但由于以下原因,这样做感觉相当不合逻辑:

  • 它使文档不清晰。
    getInstance
    '第一个参数的类型必须是
    Collection
    ,但可以是
    null
    。。。这是怎么回事? 你可以争辩说,在描述中写一行关于这一点的话会让它变得清晰,但我更喜欢澄清而不是不必要的

  • 传递
    getInstance
    任何构造参数都是错误的。
    这是因为方法名称没有明确地暗示构造,因此不清楚会发生什么

选项B

我正在考虑一种
设置
方法。此方法获取所有参数,调用类构造函数,并将内部类状态更改为
已初始化

setup
之前调用
getInstance
方法时,它将抛出
NotInitializedException
。调用安装程序后,对
setup
的任何其他调用都将导致先前初始化的异常

调用
setup
后,
getInstance
变为可用

就我个人而言,这个选择更吸引我。但感觉太过分了


你喜欢什么样的选择?为什么呢?

选择3怎么样。如果它们是真正的单例,请为它们的参数设置属性文件,以便与no-arg getInstance一起使用


如果这不合适,您可能误用了单例模式。

您正在考虑使用工厂设计模式。工厂是充当其他对象的奇特构造函数的对象。在您的情况下,您将把setup和getInstance移动到工厂。维基的文章很好-


我可能会尝试抛弃单例方法,将管理器类传递给任何需要它们的人

$manager = new Manager( $collection, $var, $var2 );

$other_class = New OtherClass( $manager );
//or
$other_class = New OtherClass;
$other_class->manager = $manager;
//or
$other_class = New OtherClass;
$other_class->setManager( $manager );

不要使用单例,请使用资源管理器(或服务容器或DI容器):

资源管理器允许您为单元测试设置任何自定义类(如依赖项注入),您只需获得所需的资源,而无需在构造函数中请求它们(我喜欢DI,但有时使用空构造函数更方便)


随时可用的变量:(我不喜欢将逻辑从代码移动到配置,但在独立模块中,它看起来是可以接受的)。

使用依赖项注入来传递
管理器
对象。不要使用单例模式。人们普遍认为,使用它会创建一个全局状态,并使API具有欺骗性

通过构造函数将
管理器
实例注入任何需要它的类。每个类都不应该尝试自己实例化
管理器
,类获取
管理器
实例的唯一方法是从构造函数获取它

class NeedsManager
{
    protected $manager;

    public function __construct(Manager $manager)
    {
        $this->manager = $manager;
    }
}

您不需要强制执行
管理器的一个实例。只是不要多次实例化它。如果所有需要
Manager
实例的类都从构造函数中获得了所需的内容,并且从未尝试单独实例化它,那么它将确保应用程序中只会有一个实例。

这不是单例,因为您可以编写
$instance=new SingletonFoo()$instance2=new SingletonFoo()
-根据定义,单例仅允许存在于一个实例中。正确。我应该对代码进行更多的验证——我试图说明工厂而不是单例。我知道工厂设计模式。不过谢谢你指出这一点。我确实喜欢用一个类来管理一次性构造的想法,但我确实觉得ManagerManager类有点过头了。你可以将工厂方法移到类本身中,但对我来说,这模糊了类应该负责的范围。再一次-1您可以使用singleton类i作为过程代码的包装器,如果您对工厂使用静态方法,则可以基于类名创建依赖项。糟糕的做法。我以前确实考虑过这一点。虽然这在我的库中可以很好地工作,但我认为这将使使用它的开发人员的工作变得更加困难。他们必须在他们的应用程序中传递我的manager类,这将给尝试将其集成到现有应用程序中带来不便。此外,管理器类永远不需要多个实例。你可以说开发人员应该意识到这一点,并采取预防措施,但我觉得这是我的库的责任,而不是使用它的开发人员。@jrs:Never-need和cant-handle是两件截然不同的事情。如果他们从来都不需要,就让他们来处理。如果它不能处理它,看看你是否可以修复它(是的,我知道我没有提供关于后者的帮助;):观看视频并learn@teresko我完全同意所说的话。然而,我担心这一原则会给将库集成到现有应用程序中带来很多困难。想象一个简单的MVC框架。当您想要调用manager类上的方法时,需要对其进行完全初始化。您必须在最高级别进行实例化,将实例传递给请求处理程序,请求处理程序将实例传递给控制器工厂,而控制器工厂在
class ResourceManager
{
    protected static $resource;

    public static function setResource($resource)
    {
        if (!empty(self::$resource)) //resource should not be overwritten
        {
            if ($resource!=self::$resource) return false;
            else return true;
        }

        self::$resource = $resource;
        return true;
    }

    public static function getResource()
    {
        return self::$resource;
    }
}
class NeedsManager
{
    protected $manager;

    public function __construct(Manager $manager)
    {
        $this->manager = $manager;
    }
}