سؤال

كانت أنماط Singleton وأنماط التسجيل بسيطة للغاية وسهلة بالنسبة لي لفهمها على الفور ولكن نمط المصنع كان شيئًا لم أتمكن من جعل عقلي يفسر 100 ٪ حتى الآن. أعتقد أنني قد أفهم ذلك الآن ، لقد كتبت عينة رمز أدناه ، يرجى المراجعة وإخبارنا إذا كان هذا هو الاستخدام الصحيح لنمط المصنع. العينة في PHP ...

<?php
 /**
 *   Factory.class.php
 */
class Factory {
    public static $_database;
    public static $_cache;
    public static $_session;

    // Build our User object with all it's dependencies  
    public static function makeUserObject()
    {
        $user = new User();
        $user->setDatabaseObject(self::$_database);
        $user->setCacheObject(self::$_cache);
        $user->setSessionObject(self::$_session);
        return $user;
    }

    // other objects will be here someday......
}

/**
 *  User.class.php
 */
class User
{
    public function __construct() { }

    // inject Database Object
    public function setDatabaseObject($databaseConnectionObject)
    {
        $this->_databaseObject = $databaseConnectionObject;
    }

    // inject Cache Object
    public function setCacheObject($cacheObject)
    {
        $this->_cacheObject = $cacheObject;
    }

    // inject Session Object
    public function setSessionObject($sessionObject)
    {
        $this->_sessionObject = $sessionObject;
    }

    // other methods here for User object...........
}

/**
 *  index.php  Main page that puts it all together
 *  assume that classes are autoloaded into this page already
 */
// Set our Database + Cache + Session objects into the Factory Object
Factory::$_database = new Databse();
Factory::$_cache = new Cache();
Factory::$_session = new Session();

// Create our User object
// The factory class will build the User object and inject all
// it's dependencies for us =)
$user = Factory::makeUserObject();

?>

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


تحديث # 1

يستند هذا إلى هذا هنا منشور مدونة قرأته هنا http://www.potstuck.com/2009/01/08/php-dependency-injection/ يشيرون إليها على أنها "مصنع" ، كنت أستخدم سجلًا ويستمر الكثير من الناس في إخباري بالنظر إلى "مصنع" وكل ما قرأته عنه لم ينقر في رأسي حتى أقرأ هذا الفن ولكن يبدو أنه ليس "مصنعًا"؟


تحديث رقم 2
من wikipedia http://en.wikipedia.org/wiki/Factory_Objectفي برمجة الكمبيوتر الموجهة للكائنات ، يعد كائن المصنع كائنًا لإنشاء كائنات أخرى. إنه تجريد من مُنشئ ، ويمكن استخدامه لتنفيذ مخططات التخصيص المختلفة ، مثل نمط المفرد. يحتوي كائن المصنع عادةً على طريقة لكل نوع من الكائنات التي يمكن إنشاؤها. تقبل هذه الطرق اختياريًا المعلمات التي تحدد كيفية إنشاء الكائن ، ثم إرجاع الكائن الذي تم إنشاؤه. يتم استخدام كائنات المصنع في المواقف التي يكون فيها الحصول على كائن من نوع معين أكثر تعقيدًا من مجرد إنشاء كائن جديد. قد يقرر كائن المصنع إنشاء فئة الكائن (إن أمكن) بشكل ديناميكي ، وإعادته من تجمع كائن ، أو قم بتكوين معقد على الكائن أو أشياء أخرى.

لذلك ربما هذا "كائن مصنع" بطريقة ما بعد ...

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

المحلول

ملخصت وتوسيع تعليقاتي من أسفل السؤال هنا

كما قال آخرون ، فهي ليست مصنع, ، ببساطة لأن نمط بهذا الاسم غير موجود. إنه إما AbstractFactory أو أ المصنع, ، على الرغم من أن الناس بشكل عملي غالباً ما يشيرون إلى إما أو بمجرد القول مصنع وهذا جيد معي.

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

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

إذا كنت لا تريد استخدام حاوية DI حاليا لهذا ، يمكنك إلقاء نظرة على zend_application وكيف يتمهشون الموارد. إنه بديل ويترك إمكانية أضف حاويات DI لاحقًا.

في الواقع ، تم حل الكثير من الموضوعات في أسئلتك السابقة في إطار Zend بالفعل ، على سبيل المثال فئات التكوين. أنا لا أقول استخدام ZF ، ولكن يمكنك التحقق من ذلك لمعرفة كيف يفعلون الأشياء. بالطبع ، يمكنك إلقاء نظرة على آخر إطار أعمال جدا.

بعض مواقع الأنماط مع أمثلة PHP:

نصائح أخرى

هذا هو نمط المصنع على ما يرام ، ولكن قد تحتاج إلى اتفاقية تسمية أفضل من مجرد تسميته Factory. كما أنه يحتوي على آثار لحقن التبعية.

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

فمثلا، Stackoverflow يمنح المستخدمين حقوقًا مختلفة اعتمادًا على درجة سمعتهم. من الناحية الافتراضية ، يمكن أن يكون لها الأنواع التالية من المستخدمين:

NewbieUser      [1-100]
BeginnerUser    [101-1000]
AverageJoeUser  [1001-5000]
VeteranUser     [5001-20000]
PowerUser       [20001-50000]
GodModeUser     [50001-100000]

ويمكن إنشاء المستخدم من خلال البحث عن ممثلهم. وتشكيل كائن المستخدم المقابل من خلال الرجوع مباشرة إلى الفصل. لا يظهر Jon Skeet في أي فئة في حال كنت تتساءل. إليك تنفيذًا كربيًا مع إنشاء مثيل مباشر:

if(reputation >= 1001 and reputation <= 5000) {
    AverageJoeUser user = new AverageJoeUser();
}

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

class UserFactory {
    public static User createUser(Integer reputation) {
        ...
    }
}

لا يبدو لي مصنعًا - يمكن أن يكون منشئًا داخليًا؟ ؛ 0)

المصنع هو وسيلة لإخفاء التنفيذ والتثبيت. وعادة ما يكون هناك بعض التجميع ، ولكن باختصار ....

  public interface IUser
    {
        void DoSomething();
    }

    public class DumbUser : IUser
    {

        public void DoSomething()
        {
            // duh... what should i do?
        }

    }

    public class SmartUser : IUser
    {

        public void DoSomething()
        {
            // calclulating prime numbers while baking bread
        }

    }


    public class UserFactory
    {
        public static IUser CreateUser()
        {
            Random r = new Random(Environment.TickCount);

            return r.Next(10) > 5 ? (IUser) new SmartUser() : new DumbUser();
        }
    }

    public class YourProgram
    {
        public void Run()
        {
            IUser user = UserFactory.CreateUser();
            user.DoSomething();
        }
    }

نظرًا لأنه يبدو أنك تريد ببساطة إنشاء مستخدم ، فأنا لا أرى الحاجة إلى عامل مجردة ، من الآن فصاعدًا يشار إليه ببساطة باسم المصنع. فكرة المصانع هي إنشاء كائنات تنفذ واجهة معينة. تريد أن تكون قادرًا على إنشاء تطبيقين مختلفين للواجهة نفسها. النقطة المهمة هي أنه قد تضطر إلى إنشاء هذه الكائنات مرارًا وتكرارًا ، وتغيرها من Objecta إلى ObjectB في جميع أنحاء الكود أمر مرهق. من السهل تبادل المصنع ، لأنه غالبًا ما يكون مفردة.

ترتبط فكرة طريقة المصنع بالأطر: تريد إنشاء استخدام في بعض رمز الإطار ، ولكن تطبيق المستخدم الفعلي في الفصول المشتقة ، أي أن هناك مستخدمين لإطار عملك في كتابة تطبيقهم الخاص - أي عندما تحتاج إلى إخبار إطار المستخدم الخاص بك "قم بإنشاء كائن مستخدم الآن" ، وهي دعوة إلى طريقة المصنع. يجب على المستخدم تنفيذ هذا. ويسمى أيضًا Contstructor الظاهري وفقًا لـ GOF.

عادةً ما يتم استخدام المنشئ عندما تكون هناك تمثيلات مختلفة للكائن ، وهذا ليس هو الحال هنا. في عيني ، يمكن تنفيذ ذاكرة التخزين المؤقت وقاعدة البيانات والجلسة كفرد ، وبالتالي تخفيف التعقيدات المعنية. خلاف ذلك ، أود أن أقترح استخدام ServiceLocator الذي يسمح لك بذلك GetDatabase, GetSession, ، إلخ. ثم ، يجب عليك تمرير الموقع إلى كائن المستخدم (والعديد من الكائنات الأخرى) عند الإنشاء. الاتجاه الصعودي هو أنه يمكن إعادة استخدام هذا المحدد عبر فصول مختلفة.

يبدو أشبه بنمط البناء بالنسبة لي. ما هو نمط المصنع الذي تعنيه بالفعل ، AbtractFactory أو FactoryMethod؟ ومع ذلك ، فإن كلاهما يتعامل مع الميراث وأنت رمز فقط يجمع كائن "معقد".

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