الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

عالم الأنماط

بدأه علاء الصالحي في 24 فبراير 2008 · 30 رد · 5,317 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

لست صاحب خبرة كبيرة في هذا المجال

لكن عملي يضطرني في بعض الأحيان إلى تعرف على بعض الأنماط

وأحببت أن أشارككم ما أعرف

وأستفيد من خبراتكم في هذا المجال

جميع المقالات التي أكتبها هنا منقولة من مدونتي

وليس لأحد الحق في نقلها دون إذن مني

موقع المدونة

لا أعلم إن كان هذا القسم هو المناسب لمثل موضوعي

إن كان هناك قسم أكثر مناسبة فأرجو من الإدارة نقل الموضوع

نمط الورقة الوحيدة Singleton

علم الأنماط من العلوم المهمة في هندسة البرمجيات

يمكن تعريفه على أنه بعض الحلول الكائنية لمشاكل قد تواجه المبرمج في أي وقت كان من عمله

في هذه السلسلة أحاول أن أضع النمط في إطار سهل بسيط

بسم الله نبدأ مع نمط الورقة الوحيدة Singleton

هذا النمط يعد من أبسط الحلول التي يقدمها علم تصميم الأنماط Design Patterns

مع بساطته إلا أنه يحل الكثير من المشاكل التي قد تواجه المبرمج

أشهر هذه المشاكل

1-الوراثة المتعددة

في بعض اللغات التي لا تدعم هذا النوع من الوراثة

يعد Singleton أحد الحلول المطروحة

2-الاقتصار على عدد معين من الكائنات لفئة معينة في أثناء التشغيل

بكل بساطة يجب أن تقوم بجعل صانع الكائنات constractur في فئتك خاص private

( على فكرة آخرة مرة أكتب فيها constratur في مقالاتي أظن أن لفظة صانع الكائنات أو البناء كافية إلى حد ما )

بهذا تكون أنهيت عمل النمط لكن كيف تقوم بحل المشاكل من خلاله

في عملية الوراثة المتعددة

قم بجعل أي صانع كائنات في فئتك خاص

قم بكتابة صانع كائنات آخر واجعله عام public واجعل المعاملات parameter المدخلة له هي الفئات التي تريد وراثتها

قم بتخزين الكائنات من هذه الفئات وبهذا تكون حصلت على حل للوراثة المتعددة

بالنسبة لعملية ضمان عدد معين من الكائنات

قم بجعل كل البنائين في فئتك مختصين بنفس الفئة private

قم بكتابة إجراء method يقوم ببناء كائن إذا كان عدد الكائنات أقل من المطلوب

إذا وصل عدد الكائنات إلى الحد المسموح فاجعل هذا الإجراء يرجع إحدى قيمتين:

1-null

2-يرجع قيمة أي عنصر من العناصر التي قمت بإنشائها

نكمل مع نمط المصنع بإذن الله

الله معكم

تم تعديل هذه المشاركة بواسطة alaadiaa في 24 فبراير 2008 في 07:30

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#2

مثال على الوراثة المتعدد في java بواسطة Singleton

public class A
{
	B b;
	private A(){
		//you can not use this constructor
	}
	public A(B b) throws Exception{
		if(b==null)
			throw new Exception("can not inhertance from null");
		this.b=b;
		System.out.println("public A constractor");
	}
}

import java.util.Calendar;
import java.util.GregorianCalendar;


public class B {
	public B(){
		System.out.println("public B constractor");
	}
	public static void main(String[] args) {
		A a;
		try {
			a = new A(null);
			System.out.println(a.b);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#3

مثال على كيفية إجبار اللغة على إنشاء كائن وحيد من هذه الفئة باستخدام Singleton

public class A
{
	A a;
	private A(){
		//you can not use this constructor out of the class
	}
	public A AObject(){
		if(a==null)
			return a=new A();
		return a;
		System.out.println("public A constractor");
	}
}

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#4

السلام عليكم

يبدو أن الموضوع يلاقي رواجاً زائداً عن الحد <_< <_<

لا عليكم أنا أجد متعتي في المواضيع التي يتجاهلها الجميع

بالنسبة للمثال الثاني هناك مشكلة

ماذا عن أكثر من خيط thread يتعاملون مع نفس الفئة class

اهااا

هنا نجد أن الفئة قد تقوم ببناء أكثر من كائن في نفس الوقت

لهذا يمكن أن نضع الدالة كدالة متزامنة في الجافا كلمة synchronized تكفي

لا أعلم عن طريقة بالنسبة لباقي اللغات

هنا يصبح شكل الشيفرة كالتالي

public class A
{
	A a;
	private A(){
		//you can not use this constructor out of the class
	}
	public synchronized A AObject(){
		if(a==null)
			return a=new A();
		return a;
		System.out.println("public A constractor");
	}
}

قمنا بعمل جيد

ماذا عن الحمل الذي تقوم به الأخت synchronized

في الغالب نحن لن نحتاجه إلا عند إنشاء الكائن الأول

بالتالي يجب علينا أن نغير الهيكلية الخاصة بالبرنامج

تحياتي

تم تعديل هذه المشاركة بواسطة alaadiaa في 1 مارس 2008 في 20:13

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#5

بالنسبة لمشكلة الحمل الذي تقوم به الأخت synchronized

يمكنا التخلص منه كالتالي

public class A
{
	A a;
	private A(){
		//you can not use this constructor out of the class
	}
	public A AObject(){
		if(a==null)
			return buildA();
		return a;
		System.out.println("public A constractor");
	}
private synchronized A buildA(){
  return a=new A();
}
}

لا توقف ما الذي قمت بعمله لقد زدت الطين بلة

لماذا؟؟

لقد عدنا إلى النقطة الأساسية

ما الذي سيحصل إن تمت عملية الفحص if statement بواسطة أكثر من خيط thread في نفس الوقت

اهاااا أظنك فهمت المشكلة

لذلك سنضع شرط فحص في نفس الدالة المتزامنة buildA

أصبحت الشيفرة كالتالي

[code]
public class A
{
	A a;
	private A(){
		//you can not use this constructor out of the class
	}
	public A AObject(){
		if(a==null)
			return buildA();
		return a;
		System.out.println("public A constractor");
	}
private synchronized A buildA(){
 if(a==null)
  return a=new A();
}
}

هكذا نكون حصلنا على شيء تقريباً كامل

الله معكم

تم تعديل هذه المشاركة بواسطة alaadiaa في 2 مارس 2008 في 07:06

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#6

كنت أريد أن أشرح الشيفرة التي تحل مشكلة تعدد الوراثة في اللغات التي لا تدعم هذه الفكرة

لكن الموضوع لا يفيد الجميع لذلك قررت تجاهلها لفترة ربما أعود لها مرة أخرى

النمط الثاني:نمط المصنع Factory

هذا النمط بسيط جداً مفيد جداً في بناء المكتبات البرمجية

المشكلة التي يحلها:

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

مثال:لو فرضنا يوجد لدينا واجهة لطابور Queue ولدينا نوعين من الطوابير طابور مبني بواسطة مصفوفة ArrayQueue

و طابور مبني بواسطة الحلقات الثنائية LinkedListQueue ويوجد لدينا مستخدم لا يعرف الفرق بين الاثنين فرضاً

طريقة الاستخدام:

نقوم ببناء فئة جديدة نسميها InterfaceFactory

هذه الفئة تحتوي دالة اسمها createInterface وتأخذ parameter يسهل على المستخدم أن يفرق به بين فئة وأخرى ممن يرثون هذه الواجهة

(بالطبع كلمة Interface سيتم استبدالها في مثالنا بطابور Queue)

نعود إلى مثالنا سنفترض أنك ستفرق بين النوعين على أساس هل هناك طول معين للطابور

هذا المثال يوضح مثالنا باستخدام الشيفرة

الواجهة طابور

public interface Queue
{
void enqueue();
Object dequeue();
}

الطابور المبني باستخدام المصفوفة

public class ArrayQueue implements Queue
{
void enqueue(){
//pula pula
}
Object dequeue(){
//pula pula
}
}

الطابور المبني باستخدام الحلقات الثنائية

public class LinkedListQueue implements Queue
{
void enqueue(){
//pula pula
}
Object dequeue(){
//pula pula
}
}

هذه الفئة المصنعة للواجهة طابور

public class QueueFactory
{
public Queue CreateQueue(string length)
{
switch (length) {
case "constant":
return new ArrayQueue ();
case "variable":
return new LinkedListQueue ();
}
return null;
}
}

ملاحظة خارج السياق:نلاحظ أن الاسم ينطبق تماماً على المسمى فالفئة فعلياً تقوم بدور المصنع الذي له واجهة غير معروف ما بداخلها

الله معكم

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#7

أهلا أخي علاء ،

أحب أن أشكرك على موضوعك الرائع ، وجزاك الله خيرا وجعله في ميزان حسناتك ..

بالنسبه لعدم وجود ردود فبسبب أن الموضوع متقدم حبتين ، ونحن مستوانا يعلم به الله ،

سأقرأ الموضوع وأعود لك ، خاصه ان موضوع Design Pattern من المواضيع الجديده علي ،

وارجوا منك أن تكمل ، وان شاء الله سوف يستفيد منه البعض عاجلا أم أجلا .

تحياتي .

http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة

https://moalfat.com  للكتب الالكترونية والكورسات التعليمية

Everything we see now is just an engineering solution based on old science

#8

إن شاء الله سأكمل

لا تخاف يا أخي

بإذن الله مادام أني بدأت الموضوع

لن يوفقني أحد أياً كان

ولكني أفكر في نقل الموضوع إلى قسم الجافا لأن الأمثلة تتعلق بالجافا

ربما أطلب ذلك من الإدارة وربما لا

تحياتي

الله معك

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#9

فقط قل أين تريد الموضوع ياعلاء

ونحن نقوم بكل ماتريده :wub:

نحن = ضمير عائد على مشرفي قسم الجافا :blush:

#10

نور الموضوع والله

والله يا أخ عيسى أنا كنت أريد طرحه في قسم الجافا

لكني آثرت أن يستفيد الجميع

المهم أظن أني أخطأت التقدير

وما منعني من طلب ذلك

إلا أني قلت في نفسي ربما يتغير الوضع

لكن وبما أنك تكلمت

فياليت ينقل إلى قسم الجافا

وشكراً

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#11

لا ادري كيف فاتني المرور على هذا الموضوع الجميل !!! سوف اقرأه إن شاء الله و لي عودة

جزاك الله الف خير ...

لا اله الا الله .. محمد رسول الله

(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)

يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين

#12

الموضوع كان في قسم البرمجيات

أنتظر عودتك

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#13

السلام عليكم ... الموضوع مشوق فعلاً .. و لدي أشياء أحب أن أناقشها هنا ....

في مسألة الوراثة المتعدد في Java بواسطة Singleton ذكرتني بمبدأ الـ Composition أو التجميع.

الفكرة أن هناك مبدأ في قبل الدخول الى الوراثة و هو إنشاء اوبجكت (أو أكثر) في داخل كلاس آخر و هي تكون إلى حد بعيد شبيهة بالوراثة المتعددة !!! لكن عملية الـ Inheritance أو الوراثة تعتبر أفضل و عملية أكثر .. فهل هناك تشابة بين الـ Composition و الـ Singleton ؟؟؟

و شكراً على هذا الموضوع

تم تعديل هذه المشاركة بواسطة بنت اليمن في 19 مارس 2008 في 21:19

لا اله الا الله .. محمد رسول الله

(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)

يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين

#14

هنا لست أعني بالوراثة المتعددة أني أقوم بذلك فعلياً

لكن هذا حل بديل يضمن لك شيء قريب بالوراثة المتعددة

لاحظي أختي شيء مهم

في عملية composition ما الذي يمنعك من أن تجعلي الكائن null

هنا نجد أنك لن تستطيعي استخدام خواصه

لكن في حالة singleton فأنت مضطرة على ذلك

في البداية أنت مضطرة إلى استخدام constructor يحتوي على هذا الكائن

ثم إن أنت أدخلت null في المدخلات لهذا الكائن ستحصلي على خطأ Exception

أتمنى أن تكون الصورة اتضحت

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#15

اعذروني على التقصير

أتمنى أن امتعكم

تحياتي

النمط الثالث:نمط الاستراتيجية Strategy

هذا النمط يستخدم في الحروب المختلفة

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

مثلاُ أنت تفضل الطعن بالسيف من أول المعركة

هذا ممل جداً

ما رأيك في بعض التغيير لماذا لا تجرب طعم اللحم

(نفسي أذوق لحم هالواحد سامعني يا عبده)

بالطبع الأخ هانيبال (التابع لفيلم صمت الحملان وليس الفاتح الإفريقي)سيكون على درجة عالية من الإنبساط لكن لسوء حظه أنه مات

بالطبع الملل ليس سبب مقنع لتكف عن الضرب بالسيف

في الغالب هناك خصم أنت تعرف أن مبارزتك له بالسيف ستأدي بك إلى الموت

تقريباً هنا نفس الفكر لكن في البرمجة

أنت تريد أن تتعامل مع جملة معينة بطريقة معينة حتى تظهر مثلاُ فاصلة منقوطة في النص تقرر أن تتعامل معها بطريقة أخرى

طريقة الحل:

قم بكتابة واجهة فيها الدوال التي تمثل الاختلاف بين الاستراتيجيات

بعد ذلك قم بوراثة الواجهة السابقة في فئات مختلفة كل فئة تمثل استراتيجية معينة

في النهاية ستقوم بكتابة فئة تحتوي على كائن من الواجهة

وفيها الدوال المساعدة خذ get وهات set ودالة تقوم باستدعام الدالة التي تحتوي على استراتيجيتك

بالطبع تغيير الاستراتيجية تعتمد على الدالة هات set

تنفيذ الاستراتيجية تعتمد على الدالة الموجودة في الفئة الأخيرة

خذ عندك المثال التالي ولنبتعد عن الحروب والدماء ماذا عن عبارات الترحيب

واجهة الترحاب

public interface HelloStrategy

{

string generateHelloString();

}

استراتيجية الترحاب بالإنجليزية

public class EnglishHelloStrategy implements HelloStrategy

{

public string generateHelloString()

{

return "Hello World!";

}

}

استراتيجية الترحاب بالعربية

public class ArabicHelloStrategy implements HelloStrategy

{

public string GenerateHelloString()

{

return "كيف حالك";

}

}

الفئة التي تحتوي على استراتيجية الترحاب

public class HelloPrinter

{

HelloStrategy helloStrategy;//هنا يوجد كائن الترحاب

public HelloStrategy getHelloStrategy {//هنا يمكنك الحصول على استراتيجية الترحاب

return helloStrategy;

}

public void setHelloStrategy {//هنا يمكنك تغيير استراتيجية الترحاب

helloStrategy = value;

}

public void PrintHello()

{//هنا يمكنك تنفيذ استراتيجية الترحاب

if (helloStrategy != null) {

ٍSystem.out.println(helloStrategy.GenerateHelloString());

}

}

}

أعلم أن هناك بعض الآنسات يتصفحن الموضوع لذا أتمنى منهن عدم قراءة الموضوع لاحتوائه على بعض مشاهد الرعب

الله معكم

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#16

أخي علاء موضوعك جميل وراقي حقيقة , لكن الذي ادى إلى قلة المشاركة و الله أعلم هو عنوان الموضوع الغامض نوعا ما .. تحياتي

#17

هل تقترح علي عنوان ما؟؟؟؟

أتمنى أن أسمع رأيك

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#18

حقيقة لا أدري بالضبط أخي علاء , لكن مثلا "تعلم برمجة OOP بالجافا" .. رمبا أفضل و الله أعلى و أعلم .

#19

المشكلة أن الموضوع لا يتكلم بالضبط عن OOP

أنا متأكد لو غيرت الاسم سيكون هناك تفاعل أكبر

لكني لا أريد أن أغش القارئ

هذا علم مشهور يسمى بـ design pattern

يتكلم عن الأساليب المستخدمة لحل مشاكل OOP

يظهر لي أن القليل هنا يعرفه

لكني حسبت أن الأغلب سيكون سمع عنه

أي اقتراحات أخرى؟؟

ولو أني بدأت أتعود على الوضع

ربما يفاد أحد من كلامي ولو بعد حين

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#20

شكرا اخي علاء على هذا الموضوع :clapping: و لكن لدي سؤال عن اسم هذا الباترن و اعتقد ان اسمه

Abstract Factory

ارجو توضيح اسم الباترن لانني اقوم الان بدراسة الباترن و لحسن حظي رايت موضوعك يتكلم عن الباترن

mofeedchaar@hotmail.com

#21

صحيح يا أخ مفيد

أتمنى من الأخوة المشرفين تعديل الاسم من Factory إلى Abstract Factory

شكراً لك أخي على تنبيهي

لأن هناك نمط آخر اسمه Method Factory

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#22

ولو يا سيد علاء و بتمنى ما تظن انو موضوعك ما عمبيلقا اهتمام لانو كل مين بدو يحترف البرمجة لازم يدرس الباترن و اللي ما بيتعلمها بيضل هاوي و هي نصيحتي لكل من يريد احتراف البرمجة لان الباترن بتعلمك كيف تتحايل على المشاكل و كيف ال OOP بتقدر تساوي المعجزات

سلاماتي لك يا اخ علاء انا عمبتابع موضوعك بشكل متواصل و بتمنى منك الاستمرار

mofeedchaar@hotmail.com

#23

شكراً لك أخي مفيد على المساندة

المشكلة تكمن في أن هذا الفصل هو فصل تخرجي

ولدي بعض المعاناة مع الأخ JBOSS

أحاول أن أكتب في المنتدى باستمرار

لكن هذا الموضوع بالذات يحتاج مني إلى جهد مضاعف

حتى أكتب شيء جيد

لكني أحاول أن ألتزم بنمط كل شهر

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#24

تعديل على الشيفرة الخاصة بنمط الورقة الوحيدة

public class A
{
  private  static A a;
	private A(){
		//you can not use this Constructor out of the class
	}
	public A AObject(){
		if(a==null)
			return buildA();
		return a;
		System.out.println("public A constractor");
	}
private synchronized A buildA(){
  return a=new A();
}
}

اعذروني فلم أنتبه للمشكلة إلا الآن

المشكلة في تعريف المتغير

يجب أن يكون كالتالي private static

private لكي لا يستطيع أحد أن يتعامل معه من خارج الفئة

static لكي تكون هناك نسخة واحدة للفئة كلها

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#25
اقتباس
-الوراثة المتعددة

في بعض اللغات التي لا تدعم هذا النوع من الوراثة

يعد Singleton أحد الحلول المطروحة

هل الــc# تدعم ما سبق ...

سؤال فضولي لا اكثر .. واذا كانت ...هل نفس المبدأ...

.

مواضيع مشابهة