Расширение синглтон-класса - PullRequest
5 голосов
/ 06 апреля 2010

Я использовал для создания экземпляра одноэлементного класса, как это:

$Singleton = SingletonClassName::GetInstance();

и для не синглтон-класса:

$NonSingleton = new NonSingletonClassName;

я думаю, что мы не должны дифференцировать, как мы создаем экземпляр класса, является ли это одиночным или нет. если я смотрю на восприятие другого класса, мне все равно, нужен ли нам класс синглтона или нет. так что мне все еще не нравится, как php относится к синглтон-классу. я думаю и всегда хочу написать:

$Singleton = new SingletonClassName;

просто еще один не синглтон-класс, есть ли решение этой проблемы?

Ответы [ 5 ]

3 голосов
/ 06 апреля 2010

Лучше будет наоборот - предоставьте фабричный метод для не-синглетонов и получите их экземпляры, используя:

$NonSingleton = NonSingletonClassName::createInstance();

Это рекомендуемая рекомендация для Java (в Effective Java ), но она применима к большинству объектно-ориентированных языков.

2 голосов
/ 06 апреля 2010

Я бы не рекомендовал это, так как это усложнило бы понимание вашего кода (люди думают, что новое означает совершенно новый объект). Но тогда я бы не рекомендовал использовать Singletons.

Основная идея этого кода заключается в том, что вокруг синглтона есть обертка. Все функции и переменные, доступные через эту оболочку, фактически влияют на синглтон. Он не идеален, так как приведенный ниже код не реализует много магических методов и интерфейсов SPL, но при необходимости их можно добавить

Код

/**
 * Superclass for a wrapper around a singleton implementation
 *
 * This class provides all the required functionality and avoids having to copy and
 * paste code for multiple singletons.
 */
class SingletonWrapper{
    private $_instance;
    /**
     * Ensures only derived classes can be constructed
     *
     * @param string $c The name of the singleton implementation class
     */
    protected function __construct($c){
        $this->_instance = &call_user_func(array($c, 'getInstance'));
    }
    public function __call($name, $args){
        call_user_func_array(array($this->_instance, $name), $args);
    }
    public function __get($name){
        return $this->_instance->{$name};
    }
    public function __set($name, $value){
        $this->_instance->{$name} = $value;
    }
}

/**
 * A test singleton implementation. This shouldn't be constructed and getInstance shouldn't
 * be used except by the MySingleton wrapper class.
 */
class MySingletonImpl{
    private static $instance = null;
    public function &getInstance(){
        if ( self::$instance === null ){
            self::$instance = new self();
        }
        return self::$instance;
    }

    //test functions
    public $foo = 1;
    public function bar(){
        static $var = 1;
        echo $var++;
    }
}

/**
 * A wrapper around the MySingletonImpl class
 */
class MySingleton extends SingletonWrapper{
    public function __construct(){
        parent::__construct('MySingletonImpl');
    }
}

Примеры

$s1 = new MySingleton();
echo $s1->foo; //1
$s1->foo = 2;

$s2 = new MySingleton();
echo $s2->foo; //2

$s1->bar(); //1
$s2->bar(); //2
1 голос
/ 17 июня 2012

Я знаю, что это действительно старый пост, но я лучше понял шаблон Factory с помощью ссылки ниже.

Так что, если это поможет будущему блуждающему. , , , здесь идет

http://www.devshed.com/c/a/PHP/Design-Patterns-in-PHP-Factory-Method-and-Abstract-Factory/1/

Было очень просто понять и понять базовую реализацию.

1 голос
/ 06 апреля 2010

Исходя из того, что ключевое слово new означает, что все, что вы хотите, не имеет значения. new создает новый экземпляр класса, поэтому он назвал new : -)

1 голос
/ 06 апреля 2010

Вы не можете создать Singleton так же, как обычный экземпляр класса. new всегда будет возвращать новый экземпляр, таким образом, вы должны иметь конструктор не публичным, и, таким образом, у вас должны быть другие средства для вызова его из класса.

Вы можете использовать фабричные методы для всех классов, например, всегда делайте getInstance(), как показано в другом ответе. Другой вариант - использовать Service Locator и Dependency Injection Framework , который знает, нужно ли возвращать что.

...