سؤال

إذا كان لديك فئة المصنع الذي يخلق كائنات جديدة من نوع ما، وتلك الفئة فاكتروي هو المفرد، مثل هذا:

class Database_Factory extends Base_Factory {
    private static $factory;
    private $objects = array();

    public function __get($profile) {
        // check for object and return it if it's created before
    }

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

ونفس كود تكرار في أي وقت حيث يحتاج بعض وجوه انها مصنع الخاصة بها. لذلك قررت أن تجعل هذه الفئة مجردة مصنع وتنفيذ إجراءات محددة فقط لكل مصنع. لكن PHP لا يسمح مثيل فئة مجردة.

abstract class Base_Factory {
    public static function getInstance(){
        if (!self::$factory)
            self::$factory = new self();
        return self::$factory;
    }
}

خطأ فادح: لا يمكن إنشاء مثيل Base_Factory فئة مجردة

وماذا كنت ستفعل؟

هل كانت مفيدة؟

المحلول

في أساليب PHP، self يشير دائما إلى فئة حيث يتم تعريف الأسلوب. منذ الإصدار 5.3.0، PHP تدعم "الراحل ثابت ملزمة"، حيث يمكنك استخدام الكلمة static للوصول إلى أساليب ثابتة متجاوزة، فضلا عن get_called_class() وظيفة للحصول على اسم فئة مشتقة في سياق ثابت.

ولكن، التصميم الخاص بك لديه عيب رئيسي: ويشارك في $factory ممتلكات ثابتة محددة في Base_Factory في جميع الفئات المشتقة منها. لذلك، لأول مرة يتم إنشاء المفرد وتخزينها في هذه الخاصية، جميع المكالمات الأخرى لgetInstance() سيعود نفس الكائن، بغض النظر عن ما يستخدم فئة مشتقة.

هل يمكن استخدام ثابتة أسماء فئة رسم الخرائط القاموس إلى المفرد قطع:

abstract class Base_Factory {
    private static $_instances = array();
    public static function getInstance() {
        $class = get_called_class();
        if (!isset(self::$_instances[$class])) {
            self::$_instances[$class] = new $class();
        }
        return self::$_instances[$class];
    }
}

وأوه، أكثر شيء واحد: إن كنت تبحث عن إمكانية إعادة استخدام رمز للكائنات المفرد يمكن أن يكون جديلة إلى حقيقة أن كنت الإفراط في استخدام نمط تصميم المفرد! اسأل نفسك إذا الطبقات كنت تخطط لتنفيذ كما سنغلتونس هي حقا سنغلتونس وإذا كان سيكون هناك أي حال من الأحوال استخدام حيث قد ترغب في أن حالات متعددة من فئة معينة.

وغالبا ما يكون أفضل بكثير لمجرد استخدام المفرد واحد يمثل "سياق التطبيق" الحالي الذي يوفر يمكنهم الدخول للكائنات التي هي الأوراق الوحيدة فيما يتعلق بهذا السياق.

نصائح أخرى

وPHP 5.3 +

abstract class Singleton
{
    /**
     * Instance
     *
     * @var Singleton
     */
    protected static $_instance;

    /**
     * Constructor
     *
     * @return void
     */
    protected function __construct() {}

    /**
     * Get instance
     *
     * @return Singleton
     */
    public final static function getInstance() {
        if (null === static::$_instance) {
            static::$_instance = new static();
        }

        return static::$_instance;
    }
}

وPHP> = 5.3 فقط

abstract class Base_Factory {
    protected static $factory;
    public static function getInstance(){
        if (!self::$factory) {
            $class = get_called_class();
            self::$factory = new $class();
        }
        return self::$factory;
    }
}

وتسجيل الأوراق الوحيدة الخاصة بك في فئة بسيطة مثل هذا

class Singletons {
    static private $singleton = array();
    public function getSingleton($class) {
    if (!isset(self::$singleton[$class])) {
        self::$singleton[$class] = new $class;
    }
    return self::$singleton[$class];
    }
}

وقم بتنفيذ هذا الإجراء

class aSingleton {
    public $i;
    public function test() {
    ++$this->i;
    echo get_class() . " called {$this->i} times\n";
    }
}

Singletons::getSingleton('aSingleton')->test();
Singletons::getSingleton('aSingleton')->test();

والناتج

aSingleton called 1 times
aSingleton called 2 times

وبحكم التعريف classess مجردة لا يمكن إنشاء مثيل في PHP مثل أي لغة أخرى وجوه المنحى. لذلك ينبغي أن يكون Base_Factory الخاص واجهة بدلا من فئة مجردة.

ومن دليل PHP: "لا يجوز لإنشاء مثيل من الفئة التي تم تعريفها بأنها مجردة"

وحسنا يمكنك أن تفعل فحص للتأكد من الطبقة استدعاء الدالة ليست Base_Factory.

if(__CLASS__!='Base_Factory')

وثم استخدم $ هذا بدلا من النفس للإشارة إلى الكائن الحالي بدلا من فئة الحالية.

if (!$this->factory)
        $this->factory = new self();
    return $this->factory;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top