5

我想要一个库类来维护同一个请求的状态。我的用例是我想将“消息”传递给班级,然后随时从视图中调用它们。可以从应用程序的任何部分添加消息。

我最初是通过静态方法完成的,效果很好。但是,作为库的一部分,我还需要调用__constructand __destruct(),这不能在静态类上完成。

这是我正在尝试做的一个非常简单的示例:

class Messages
{
  private static $messages = array();

  public function __construct()
  {
    // do something
  }

  public function __destruct()
  {
    // do something else
  }

  public static function add($message)
  {
    self::$messages[] = $message;
  }
  public static function get()
  {
    return self::$messages;
  }
}

然后我可以在我的代码中的任何地方添加消息

Messages::add('a new message');

如果可能的话,我想避免使用静态(可测试性)。我看过 DI,但它似乎不合适,除非我遗漏了什么。

我可以创建一个类(非静态),但是我如何确保所有消息都写入同一个对象 - 以便我以后可以检索它们?

解决这个问题的最佳方法是什么?

4

5 回答 5

3

我看起来你可以从使用单例模式中受益——它是为一个在整个请求中必须只有一个实例的对象设计的。基本上,您创建一个私有构造函数和一个静态方法来检索唯一的实例。这是一个将执行您描述的单例的示例。

<?php
class Messages
{
    private static $_instance;
    private $_messages = array();

    private function __construct() {
        // Initialize
    }

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

    public function add_message( $msg ) {
        $this->_messages[] = $message;
    }

    public function get_messages() {
        return $this->_messages;
    }

    private function __destruct() {
        // Tear-down
    }
}

$my_messages = Messages::instance();
$my_messages->add_message( 'How now, brown cow?' );
// ...
$your_messages = Messages::instance();
$msgs = $your_messages->get_messages();
echo $your_messages[0]; // Prints, "How now, brown cow?"

由于构造函数是私有的,因此您只能Messages从对象本身的方法中创建对象。由于您有一个静态方法,instance()因此您可以从那里创建一个新Messages实例。但是,如果一个实例已经存在,您希望返回该实例。

基本上,单例是它自己实例的看门人,它顽固地拒绝让自己的实例存在多个。

于 2012-09-07T16:46:25.243 回答
1

听起来你想做一个单例类。这将在一个类中创建一个实例,并允许您访问另一个类中的同一实例。查看http://www.developertutorials.com/tutorials/php/php-singleton-design-pattern-050729-1050/了解更多信息。

于 2012-09-07T16:39:37.743 回答
1

让它成为一个单例类怎么样?

class Messages
{
    // singleton instance of Messages
    private static $instance;

    public function __construct() { ... }

    public static function getInstance()
    {
        if (!self::$instance)
        {
            self::$instance = new Messages();
        }

        return self::$instance;
    }
}

这将确保您的所有消息都写入同一个对象,并且还允许您调用__construct__destruct

于 2012-09-07T16:41:30.300 回答
0

您需要的是单例模式:

final class Singleton {
    // static variable to store the instance
    private static $instance = NULL;

    // disable normal class constructing
    private function __construct() {}

    // instead of using the normal way to construct the class you'll use this method
    public static function getInstance() {
       if (NULL === self::$instance) {
           self::$instance = new self;
       }
       return self::$instance;
    }
    // disable external cloning of the object
    private function __clone() {}
}

// get the instance across some of your scripts
$singleton = Singleton::getInstance();
于 2012-09-07T16:39:39.983 回答
0

听起来有点像你想要一个单例,尽管作为一种反模式我会避免它。

您可以创建一个完整的静态类,其中每个静态成员调用一个self::_isBuilt();方法来执行您的构造元素。Destruct 有点棘手。

满足您需求的最佳情况可能是您立即构建的普通(非静态)类,然后从全局访问......不是超级整洁,但允许构造/破坏和成员,以及您使用的静态变量$this可能是有帮助。如果你不喜欢全局变量,你也可以将它包装在一个方法中(在 JS 中使用的技巧相当多),但它并不是真的更整洁。

作为一个普通的全局类:

$myClass=new myClass();
//Access anywhere as:
globals['myClass']->myFunction(..);

封装在一个函数中

function my_class() {
 static $var=null;
 if ($var===null) $var=new myClass();
 return $var;
}
//Access anywhere as:
my_class()->myFunction(..);
于 2012-09-07T16:45:15.033 回答