سؤال

دعونا نقول أنا أكتب PHP (>= 5.0) الفئة التي من المفترض أن يكون المفرد.جميع مستندات قرأت قول لجعل منشئ فئة خاصة فئة لا يمكن أن تكون مباشرة مثيل.

حتى إذا كان لدي شيء من هذا القبيل:

class SillyDB
{
  private function __construct()
  {

  }

  public static function getConnection()
  {

  }
}

هل هناك أي حالات __construct() يسمى خلاف إذا أنا أفعل

new SillyDB() 

الاتصال داخل الطبقة نفسها ؟

و لماذا أنا يسمح له مثيل SillyDB من داخل نفسها في كل شيء ؟

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

المحلول

__construct() إلا إذا دعا الأمر من خلال طريقة الطبقة التي تحتوي على الخاص منشئ.حتى بالنسبة إلى المفرد ، قد يكون وسيلة مثل ذلك:

class DBConnection
{
   private static $Connection = null;

   public static function getConnection()
   {
      if(!isset(self::$Connection))
      {
         self::$Connection = new DBConnection();
      }
      return self::$Connection;
   }

   private function __construct()
   {

   }
}

$dbConnection = DBConnection::getConnection();

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


تحرير: وأضاف $ ، كما اقترح @emanuele-del-grande

نصائح أخرى

هنا هو بسيط جدا المفرد فقط يولد الوقت/التاريخ:

class TheDate
{
    private static $DateInstance = null;
    private $dateVal;

    public static function getDateInstance()
    {
        if(!isset(self::$DateInstance))
        {
            self::$DateInstance = new TheDate();
        }

        return self::$DateInstance;
    }

    public static function getDateVal()
    {
        return self::$DateInstance->dateVal;
    }

    private function __construct()
    {
        $this->dateVal = strftime("%Y-%m-%d %H:%M:%S");
    }
}

تفعل شيئا مثل هذا لا يعطيني نفس التاريخ مرارا وتكرارا:

$date1 = TheDate::getDateInstance();
echo $date1->getDateVal() . "<br />";

$date2 = TheDate::getDateInstance();
echo $date2->getDateVal() . "<br />";

والقيام بذلك لا تولد أي أخطاء:

class NewDate extends TheDate
{
    public function __construct()
    {

    }
}

حسنا ، لقد أجريت بعض الاختبارات من بلدي.

  • إذا كنت لا تعلن الخاصة بك المنشئ في فرعية ، في محاولة إنشاء مثيل وسوف رمي خطأ فادح لأنه يحاول الاتصال الفائقة منشئ.
  • في حالة اتصال DB, عندما كنت من المفترض العودة (في PHP, على أي حال) ، mysqli سبيل المثال أو الموارد التي تم إرجاعها من قبل mysql_connect() وظيفة (أو صلة أخرى RDBMS) ، طالما يمكنك وضع علامة على سبيل المثال خاصة انه ليس هناك تهديد من شخص subclassing و العبث مع الرابط.
  • كما أشرت من قبل ، إذا كان شخص ما يريد حقا أن تجاوز السلوك الخاص بك وإجراء اتصالات متعددة, أنها يمكن أن تفعل ذلك قبل كتابة فصل جديد.

اختبار التعليمات البرمجية, مارك, واسمحوا لي أن أعرف ما تجد.

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

الفائدة العملية المفرد في هذه الحالة هو أن استخدامه, يمكنك التأكد من أن كنت دائما باستخدام نفس اتصال قاعدة البيانات لفترة معينة طلب HTTP.فإنه يحقق ذلك.الأشياء الأخرى (باستخدام final و خاصة المنشئات) ومن المفيد أن نعرف من نظرية المنظور ، وحتى أكثر من المفيد أن نعرف إذا كنت ترغب في توزيع API-رمز الجودة أخرى المبرمجين, ولكن في حالة هذا المثال بالذات ، كل الكلمات تقوم به هو إضافة بايت إلى صفك حجم الملف.

قليلا أحمق اختيار:للتأكد من اكتمالها ربما تعلن الدرجة النهائية جدا منذ كنت لا تريد شخص ما subclassing هذه الفئة و تنفيذ منشئ العام.

(يغفر لي إذا كان المترجم يمسك تجاوز خاص منشئ, ولكن أنا لا أعتقد أنه يفعل)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top