1. نظرة عامة
بشكل عام ، تنقسم أنماط التصميم إلى ثلاث فئات:
(1) الوضع الإبداعي ، ما مجموعه خمسة أنواع: وضع طريقة المصنع ، وضع المصنع التجريدي ، وضع Singleton ، وضع المنشئ ، ووضع النموذج الأولي.
(2) الأوضاع الهيكلية ، ما مجموعه سبعة أنواع: وضع المحول ، وضع الديكور ، وضع الوكيل ، وضع المظهر ، وضع الجسر ، وضع المركب ، وضع التمتع.
(3) الوضع السلوكي ، ما مجموعه أحد عشر: وضع السياسة ، وضع طريقة القالب ، وضع المراقب ، الوضع الفرعي التكراري ، وضع سلسلة المسؤولية ، وضع الأوامر ، وضع المذكرة ، وضع الحالة ، وضع الزوار ، وضع الوسيط ، ووضع المترجم.
2. ستة مبادئ نموذج التصميم
1. فتح مبدأ الإغلاق
مبدأ الفتح والإغلاق هو الانفتاح على الامتدادات وقرب التعديلات. عندما يحتاج البرنامج إلى توسيع نطاق ، لا يمكنك تعديل الكود الأصلي لتحقيق تأثير ساكن ساخن.
2. مبدأ استبدال Liskov
وصفها الرسمي مجردة نسبيًا ويمكن استخدامه في Baidu. في الواقع ، يمكن فهمه على النحو التالي: (1) يجب أن تكون قدرة الفئة الفرعية أكبر من أو تساوي الفئة الأصل ، أي الطرق التي يمكن أن تستخدمها فئة الأصل ، ويمكن أن تستخدم الفئة الفرعية. (2) وينطبق الشيء نفسه بالنسبة لقيمة الإرجاع. لنفترض أن طريقة فئة الوالدين تُرجع قائمة وإرجاع الفئة الفرعية إلى قائمة ArrayList ، والتي يمكن القيام بها بالطبع. إذا كانت طريقة فئة الأصل تُرجع قائمة ArrayList وإرجاع فئة الطفل قائمة ، فهذا لا معنى له. هنا قدرة الفئات الفرعية على إرجاع القيم أصغر من تلك الموجودة في فئات الوالدين. (3) هناك أيضًا حالات يتم فيها إلقاء استثناءات. يمكن لأي طريقة فئة فرعية أن تعلن عن فئة فرعية ترمي طريقة فئة الأصل لإعلان استثناء.
لا يمكن أن يعلن أن استثناء أن فئة الوالدين لم تعلن.
3. مبدأ انعكاس الاعتماد
هذا هو أساس مبدأ الفتح والإغلاق ، والمحتوى المحدد: البرمجة الموجهة للواجهة ، بالاعتماد على التجريد بدلاً من الخرسانة.
4. مبدأ الفصل في الواجهة
هذا المبدأ يعني: استخدام واجهات معزولة متعددة أفضل من استخدام واجهة واحدة. وهذا يعني أيضا تقليل درجة الاقتران بين الفصول. من هنا يمكننا أن نرى أن نمط التصميم هو في الواقع فكرة تصميم البرنامج ، بدءًا من بنية برمجيات كبيرة ، لراحة الترقية والصيانة. لذلك ، ظهرت المقالة أعلاه عدة مرات: تقليل الاعتماد وتقليل الاقتران.
5. مبدأ ديميتر
لماذا مبدأ أقل المعرفة؟ وهذا يعني أن كيان واحد يجب أن يتفاعل مع كيانات أخرى أقل من ذلك بكثير ، بحيث تكون الوحدات الوظيفية للنظام مستقلة نسبيًا.
6. مبدأ إعادة الاستخدام المركب
المبدأ هو محاولة استخدام طرق التوليف/التجميع بدلاً من الميراث.
3. وضع الخلق
هناك خمسة أنواع من أوضاع الإنشاء: وضع طريقة المصنع ، وضع المصنع التجريدي ، وضع Singleton ، وضع المنشئ ، ووضع النموذج الأولي.
3.1. نموذج طريقة المصنع
ينقسم وضع طريقة المصنع إلى ثلاثة أنواع: وضع المصنع العادي ، ووضع طريقة المصنع المتعدد ووضع طريقة المصنع الثابت.
3.1.1. نموذج المصنع العادي
نموذج المصنع العادي هو إنشاء فئة المصنع وإنشاء مثيلات من بعض الفئات التي تنفذ الواجهة نفسها.
حزمة com.mode.create ؛ الواجهة العامة myInterface {public void print () ؛} حزمة com.mode.create ؛ الطبقة العامة myClassone تنفذ myInterface {Override public void print () {system.out.println ("myClassone") ؛ }} حزمة com.mode.create ؛ الفئة العامة myClasStwo تنفذ myInterface {Override public void print () {system.out.println ("myClasStwo") ؛ }} حزمة com.mode.create ؛ الفئة العامة myfactory {public myInterface Produce (نوع السلسلة) {if ("One" .equals (type)) {return new myclassone () ؛ } آخر إذا ("two" .equals (type)) {return new MyClasStwo () ؛ } آخر {system.out.println ("لا يوجد نوع يمكن العثور عليه") ؛ العودة لاغية. }}} حزمة com.mode.create ؛ الفئة العامة FactoryTest {public static void main (string [] args) {myfactory factory = new MyFactory () ؛ myInterface myi = factory.produce ("one") ؛ myi.print () ؛ }}أعتقد أن نتائج FactoryTest يجب أن تكون واضحة.
دعونا نفهم هذه الجملة مرة أخرى: نموذج المصنع العادي هو إنشاء فئة المصنع وإنشاء مثيلات من بعض الفئات التي تنفذ الواجهة نفسها.
3.1.2. أوضاع طريقة المصنع المتعددة
تعتبر أوضاع طريقة المصنع المتعددة تحسنا لوضع طريقة المصنع العادي. تتمثل أوضاع طريقة المصنع المتعددة في توفير طرق مصنع متعددة لإنشاء كائنات بشكل منفصل.
دعونا نلقي نظرة على الكود مباشرة. نقوم بتعديل myfactory و factorytest على النحو التالي:
حزمة com.mode.create ؛ الفئة العامة myFactory {public myInterface productone () {return new myclassone () ؛ } public myInterface producetwo () {return new MyClasStwo () ؛ }} حزمة com.mode.create ؛ الفئة العامة FactoryTest {public static void main (string [] args) {myfactory factory = new MyFactory () ؛ myInterface myi = factory.produceOne () ؛ myi.print () ؛ }}نتائج التشغيل واضحة للغاية.
دعونا نفهم هذه الجملة مرة أخرى: تعتبر أوضاع طريقة المصنع المتعددة تحسنا لوضع طريقة المصنع العادي. تتمثل أوضاع طريقة المصنع المتعددة في توفير طرق مصنع متعددة لإنشاء كائنات بشكل منفصل.
3.1.3. وضع طريقة المصنع الثابت
وضع طريقة المصنع الثابت ، قم بتعيين الأساليب في أوضاع طريقة المصنع المتعددة أعلاه إلى ثابت ، وليس هناك حاجة لإنشاء مثيل ، فقط اتصل به مباشرة.
دعونا نلقي نظرة على الكود مباشرة. نقوم بتعديل myfactory و factorytest على النحو التالي:
حزمة com.mode.create ؛ الفئة العامة myfactory {public static myInterface productone () {return new myclassone () ؛ } static myinterface producetwo () {return new myclasstwo () ؛ }} حزمة com.mode.create ؛ الفئة العامة FactoryTest {public static void main (string [] args) {myInterface myi = myfactory.produceone () ؛ myi.print () ؛ }}لا تزال نتائج العملية واضحة للغاية.
مراجعة مرة أخرى: وضع طريقة المصنع الثابت ، واضبط الأساليب في أوضاع طريقة المصنع المتعددة أعلاه إلى ثابت ، وليس هناك حاجة لإنشاء مثيل ، فقط اتصل به مباشرة.
3.2. نمط المصنع التجريدي
هناك مشكلة في نموذج طريقة المصنع الذي يعتمد عليه إنشاء الفصل على فئات المصنع ، أي إذا كنت ترغب في توسيع البرنامج ، فيجب عليك تعديل فئة المصنع ، التي تنتهك مبدأ الإغلاق.
لحل هذه المشكلة ، دعونا نلقي نظرة على نمط المصنع التجريدي: إنشاء فئات مصنع متعددة ، بحيث تكون هناك حاجة إلى وظائف جديدة ، يمكنك إضافة فئات مصنع جديدة مباشرة ، دون تعديل الكود السابق.
هذا يتوافق مع مبدأ الإغلاق.
لنلقي نظرة على الكود أدناه:
MyInterface ، myclassone ، myclasstwo لا يزال دون تغيير.
تتم إضافة الواجهات والفصول التالية:
حزمة com.mode.create ؛ Public Interface Provider {public myInterface Produce () ؛ } package com.mode.create ؛ الطبقة العامة myFactoryOne تنفذ موفر {Override public myInterface Produce () {return new myclassone () ؛ }} package com.mode.create ؛ الطبقة العامة myfactorytwo تنفذ موفر {override public myInterface Produce () {return new MyClasStwo () ؛ }}قم بتعديل اختبار فئة الاختبار على النحو التالي:
حزمة com.mode.create ؛ الفئة العامة FactoryTest {public static void main (string [] args) {provider provider = new MyFactoryOne () ؛ myInterface myi = provider.produce () ؛ myi.print () ؛ }}نتائج التشغيل لا تزال واضحة.
مراجعة مرة أخرى: نمط المصنع التجريدي هو إنشاء فئات مصنع متعددة ، بحيث تكون هناك حاجة إلى وظائف جديدة ، يمكنك إضافة فئات المصنع الجديدة مباشرةً ، دون تعديل الكود السابق.
3.3. وضع Singleton
نمط Singleton ، لا حاجة إلى الكثير من التفسير.
فقط انظر إلى الكود:
اختبار الحزمة الطبقة العامة myobject {private static myobject myobject ؛ private myobject () {} public static myobject getInstance () {if (myObject! = null) {} else {myObject = new myobject () ؛ } إرجاع myobject ؛ }}ومع ذلك ، فإن هذا سيؤدي إلى مشاكل متعددة الخيوط. للحصول على شرح مفصل ، يمكنك رؤية الفصل 6 في كتاب "Core Technology of Java Multi-Thrheading Programming".
3.4. وضع البناء
نمط المنشئ: هو فصل كائن معقد عن تمثيله ، بحيث يمكن لعملية البناء نفسها إنشاء تمثيلات مختلفة.
تبدو مجردة للغاية حرفيًا ، لكنها في الواقع أيضًا مجردة للغاية! ! ! !
عادةً ما يتضمن وضع البناء الأحرف التالية:
(1) المنشئ: أعط واجهة مجردة لتوحيد بناء مكونات مختلفة من كائن المنتج. تحدد هذه الواجهة أجزاء من الكائنات المعقدة التي يتم إنشاؤها ، ولا تتضمن إنشاء مكونات كائن محددة.
(2) ConcreteBuilder: ينفذ واجهة البناء ، ويحدد إنشاء أجزاء مختلفة من الكائنات المعقدة لمنطق الأعمال المختلفة. بعد اكتمال عملية البناء ، يتم تقديم مثال على المنتج.
(3) المخرج: يستدعي بناة محددة لإنشاء أجزاء مختلفة من الكائنات المعقدة. لا يتضمن المدرب معلومات منتج محددة ، ولكنه مسؤول فقط عن ضمان إنشاء جميع أجزاء الكائن سليمة أو بترتيب معين.
(4) المنتج: الكائن المعقد ليتم إنشاؤه.
من الشائع بناء الأشرار في تطوير اللعبة ، والشرط هو: يجب أن يشمل الأشرار الرأس والجسم والقدمين.
لنلقي نظرة على الكود التالي:
المنتج (كائن معقد يتم إنشاؤه.):
حزمة com.mode.create ؛ الشخص العام {Private String Head ؛ سلسلة سلسلة خاصة قدم سلسلة خاصة السلسلة العامة gethead () {return head ؛ } public void sethead (string head) {this.head = head ؛ } السلسلة العامة getBody () {return Body ؛ } public void setBody (سلسلة سلسلة) {this.body = body ؛ } سلسلة عامة getFoot () {return foot ؛ } public void setfoot (String foot) {this.foot = foot ؛ }} BUILDER (يعطي واجهة مجردة لتوحيد بناء مكونات مختلفة لكائن منتج. تحدد هذه الواجهة أجزاء من كائن معقد يتم إنشاؤها ليتم تنفيذها ، ولا تتضمن إنشاء مكونات كائن محددة.):):):
حزمة com.mode.create ؛ الواجهة العامة personBuilder {void buildhead () ؛ void buildbody () ؛ void buildfoot () ؛ شخص بني () ؛} ConcreteBuilder (تنفذ واجهة البناء ، التي تجسد إنشاء أجزاء مختلفة من الكائنات المعقدة لمنطق الأعمال المختلفة. بعد اكتمال عملية البناء ، تقدم مثالًا على المنتج.):
حزمة com.mode.create ؛ الطبقة العامة manbuilder تنفذ personbuilder {شخص الشخص ؛ manbuilder العامة () {person = new person () ؛ } public void buildbody () {person.setBody ("بناء جسم الرجل") ؛ } public void buildfoot () {person.setFoot ("بناء أقدام الرجل") ؛ } public void buildhead () {person.sethead ("بناء رأس الرجل") ؛ } الشخص العام buildperson () {return person ؛ }} المخرج (اتصل بالبناء المحدد لإنشاء أجزاء مختلفة من الكائنات المعقدة. لا يتضمن المدرب معلومات منتج محددة. إنه مسؤول فقط عن ضمان إنشاء أجزاء الكائن سليمة أو بترتيب معين.):
حزمة com.mode.create ؛ الطبقة العامة persondirector {public person ConstructPerson (personbuilder pb) {pb.buildhead () ؛ pb.buildbody () ؛ pb.buildfoot () ؛ إرجاع pb.buildperson () ؛ }} فئة الاختبار:
حزمة com.mode.create ؛ اختبار الفئة العامة {public static void main (string [] args) {persondirector pd = new persondirector () ؛ شخص الشخص = pd.constructPerson (manbuilder () جديد) ؛ System.out.println (person.getBody ()) ؛ System.out.println (person.getFoot ()) ؛ system.out.println (person.gethead ()) ؛ }}نتائج التشغيل:
مراجعة: نمط البناء: هو فصل بناء كائن معقد عن تمثيله ، بحيث يمكن لعملية البناء نفسها إنشاء تمثيلات مختلفة.
3.5. وضع النموذج الأولي
تتمثل فكرة هذا النمط في استخدام كائن كنموذج أولي ، ونسخه واستنساخه ، وإنتاج كائن جديد مشابه للكائن الأصلي.
عند الحديث عن نسخ الأشياء ، سأتحدث عن ذلك مع نسخ ضحل ونسخ عميق للأشياء. بادئ ذي بدء ، تحتاج إلى فهم مفهوم النسخ العميق والضحل للأشياء:
نسخة ضحلة: بعد نسخ كائن ، سيتم إعادة إنشاء متغيرات نوع البيانات الأساسية ، بينما يشير نوع المرجع إلى الكائن الأصلي.
نسخة عميقة: بعد نسخ كائن ما ، يتم إعادة إنشاء كل من نوع البيانات الأساسية ونوع المرجع. ببساطة ، يتم نسخ النسخ العميق بالكامل ، في حين أن النسخ الضحل ليس دقيقًا.
اكتب مثالًا على نسخ عمق:
حزمة com.mode.create ؛ استيراد java.io.bytearrayinputStream ؛ استيراد java.io.bytearrayoutputstream ؛ استيراد java.ioException ؛ استيراد java.io.objectinputStream ؛ استيراد java.io.objectoututream ؛ import java.io.serializable ؛ النموذج الأولي للطبقة العامة ينفذ استنساخ ، قابل للتسلسل {{private static final long serialversionuid = 1L ؛ قاعدة int الخاصة عدد صحيح خاص OBJ ؛ /* نسخة ضحلة*/ كائن عام clone () رمي clonenotsupportedException {// لأن الواجهة القابلة للاستنساخ هي واجهة فارغة ، يمكنك تحديد اسم طريقة فئة التنفيذ في Will // مثل clonea أو cloneb ، لأنها الموسيقية ، هو الموضعية هنا هو الجملة super.clone () // super.clone () clone clone () النموذج الأولي proto = (النموذج الأولي) super.clone () ؛ إرجاع بروتو } /* نسخة عميقة* / كائن عام deepclone () يلقي ioException ، classnotfoundException { /* اكتب الدفق الثنائي إلى الكائن الحالي* / bytearrayoutputstream bos = جديد bytearrayoutputstream () ؛ ObjectOutputStream OOS = New ObjectOutputStream (BOS) ؛ OOS.WriteObject (هذا) ؛ /* اقرأ الكائن الجديد الذي تم إنشاؤه بواسطة الدفق الثنائي*/ bytearrayinputstream bis = جديد bytearrayinputstream (bos.tobytearray ()) ؛ ObjectInputStream OIS = New ObjectInputStream (BIS) ؛ إرجاع OIS.ReadObject () ؛ } public int getBase () {return base ؛ } public void setBase (int base) {this.base = base ؛ } integer getObj () {return obj ؛ } public void setObj (integer obj) {this.obj = obj ؛ }} فئة الاختبار:
حزمة com.mode.create ؛ استيراد java.io.ioException ؛ اختبار الفئة العامة {public static void main (string [] args) يلقي clonenotsupportedException ، classnotfoundException ، ioException {prototype النموذج الأولي = جديد النموذج الأولي () ؛ النموذج الأولي. النموذج الأولي. /* نسخة ضحلة*/ النموذج الأولي النموذجي 1 = (النموذج الأولي) النموذج الأولي. /* نسخة عميقة*/ النموذج الأولي النموذجي 2 = (النموذج الأولي) النموذج الأولي. deepclone () ؛ system.out.println (prototype1.getObj () == OrityType1.getObj ()) ؛ system.out.println (prototype1.getObj () == OrityType2.GetObj ()) ؛ }}نتائج التشغيل:
ما سبق هو كل شيء عن هذا المقال ، آمل أن يكون مفيدًا لتعلم الجميع.