PHP静态v单例类-ConnectionFactory解释

PHP静态v单例类-ConnectionFactory解释,php,static,singleton,Php,Static,Singleton,我是这一级别的PHP编程新手,我一直在读一篇关于单例和静态类的文章。我正在编写一个类,它将促进我的数据库连接 我遇到了Jon Raphaelson()编写的以下代码: 看起来我已经找到了我想要的东西,但是我有一些问题 self::$factory=新连接工厂(…)-我在这个类中没有看到构造函数。我是否只是创建这个构造函数并传入数据库详细信息(“dbname”、“user”、“pass”等) 函数,我假设它的目的是将所有实际的函数都放在ConnectionFactory类中检索数据,这就是这个函数

我是这一级别的PHP编程新手,我一直在读一篇关于单例和静态类的文章。我正在编写一个类,它将促进我的数据库连接

我遇到了Jon Raphaelson()编写的以下代码:

看起来我已经找到了我想要的东西,但是我有一些问题

  • self::$factory=新连接工厂(…)-我在这个类中没有看到构造函数。我是否只是创建这个构造函数并传入数据库详细信息(“dbname”、“user”、“pass”等)
  • 函数,我假设它的目的是将所有实际的函数都放在ConnectionFactory类中检索数据,这就是这个函数在这个类中的原因。否则,我会期望这个函数在另一个类中。[编辑]跳过这个问题,我没有看到一个括号
  • 当两个用户登录到站点并请求DB连接(两个用户都在进行更新等)时会发生什么情况?这是一个单身问题吗

  • 谢谢

    工厂是一个单独的工厂,因为您不需要多个工厂

  • 您不需要构造函数,可以通过getFactory()方法为工厂设置所需的任何状态。getFactory()函数不获取连接,因此不要在此处执行任何与连接相关的设置,但不要执行连接对象本身。工厂为您使用的类“构建实例”,因此您可以使用getConnection()方法设置状态并构造工厂应该生成的连接对象
  • getSomething()不是ConnectionFactory类中的方法,它只是使用factory类获取工厂,然后获取连接的示例
  • 我个人讨厌PHP中的方法链接。getSomething()中真正发生的是:

  • 类不需要显式构造函数就可以用
    new ClassName()
    实例化。然而,如果该类被认为是一个单例(在本例中看起来是这样的),那么模式的整个要点就是使此类实例化无法从类外部进行,这就是为什么我认为应该有一个使用
    private
    关键字声明的构造函数

  • get
    getSomething()
    是一个“独立”函数,包含使用类的示例

  • 不可以。多个用户使用多个PHP实例处理您的脚本,他们之间没有共享任何内容

  • 这主要是为了扩大我在问题下的评论

    更好的“单身”模式是:

    class ConnectionFactory {
    
        protected static $connection;
    
        public function getConnection() {
            if (!self::$connection) {
                self::$connection = new PDO(...);
            }
            return self::$connection;
        }
    
    }
    
    此工厂的用户应该期望它的一个实例,而不是自己调用它:

    class Foo {
    
        protected $connectionFactory;
    
        public function __construct(ConnectionFactory $factory) {
            $this->connectionFactory = $factory;
        }
    
        public function somethingThatNeedsAConnection() {
            $connection = $this->connectionFactory->getConnection();
            ...
        }
    
    }
    
    $foo = new Foo(new ConnectionFactory);
    
    这允许
    Foo
    在需要时获得连接本身,但也允许您向
    Foo
    注入一些替代连接,例如用于测试目的

    作为一种方便的措施和降低实例化复杂性的方法,此模式也很好:

    class Foo {
    
        protected $connectionFactory;
    
        public function __construct(ConnectionFactory $factory = null) {
            if (!$factory) {
                $factory = new ConnectionFactory;
            }
            $this->connectionFactory = $factory;
        }
    
        ...
    
    }
    

    这仍然允许注入和重写依赖项,但它不要求每次实例化
    Foo

    时都注入工厂,我建议不要使用这种模式。请参阅了解原因和备选方案。@deceze您是否建议PHP用户不要使用Factory模式或Singleton模式?我不知道为什么它们本质上是坏的——它们是经过严格审查的OOP模式。@Ray我反对单例模式,更具体地说是反对静态调用
    ConnectionFactory::getFactory()
    anywhere。如果您使用的是工厂,那么应该将该工厂作为对象注入,而不是静态调用。单件工厂是毫无意义的。工厂应该用来为对象A提供构造其他对象B的方法,而无需将A静态耦合到B。因此,将A静态耦合到工厂B没有任何好处。@deceze如何强制不创建工厂或连接的多个副本?例如,对于资源有限的事物,例如连接到数据库,您或使用代码的人可能会意外地创建比可用连接更多的连接。诚然,这是更多可测试的方法和类,但这样做也更有可能创建单元测试正常工作的情况,但当预期的连接被拒绝或由于资源争用而超时时,整个代码都会中断。@Ray将实例化的连接另存为工厂的
    静态
    属性。您可以根据需要实例化任意多个工厂,但它们都只提供一个连接。更好的方法是,只在调用链中的某个较高位置创建一次连接,并使用依赖项注入将其传递到每个需要它的对象中。Ray,谢谢(还有#2上的oops,不确定我为什么错过了它,可能原始帖子的间距不同)。@NEW2WEB没问题,请查看我的更新。希望它能解决一切问题。
    class Foo {
    
        protected $connectionFactory;
    
        public function __construct(ConnectionFactory $factory) {
            $this->connectionFactory = $factory;
        }
    
        public function somethingThatNeedsAConnection() {
            $connection = $this->connectionFactory->getConnection();
            ...
        }
    
    }
    
    $foo = new Foo(new ConnectionFactory);
    
    class Foo {
    
        protected $connectionFactory;
    
        public function __construct(ConnectionFactory $factory = null) {
            if (!$factory) {
                $factory = new ConnectionFactory;
            }
            $this->connectionFactory = $factory;
        }
    
        ...
    
    }