Skip to content
Milad Khajavi edited this page Mar 25, 2013 · 55 revisions

تکنیک‌های برنامه‌نویسی

Inversion of control (IoC)

  1. What is Inversion of Control?
  2. Inversion of Control Containers and the Dependency Injection pattern

Design Principles

  1. Encapsulate what varies.
  2. Programming to interface not implementation.
  3. decouple the client code from actual implementation.
  4. Depenency Inversion Principle: Depend upon abstractions. Do not depend on concrete classes. Our high-level components should not depend on our low-level components; rather than, they should both them depend on abstractions. [p141 HeadFirst] Depend on abstractions, not on concretions.

SOLID

Single responsibility principle (SRP)

a class should have only a single responsibility.

Open/closed principle (OCP)

“software entities … should be open for extension, but closed for modification”.

Liskov substitution principle (LSP)

“objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program”. See also design by contract.

Interface segregation principle (ISP)

“many client-specific interfaces are better than one general-purpose interface.”

Dependency inversion principle (DIP)

one should “Depend upon Abstractions. Do not depend upon concretions.” Dependency injection is one method of following this principle.

  1. High level modules should not depend upon low-level modules. Both should depend upon abstractions.

  2. Abstractions should never depend upon details. Details should depend upon abstractions.

  3. Any changes of the low level implementations do not force the high level module to change.

  4. in traditional, non-inverted control higher-level components depend on lower-level ones.

  5. With inversion of control, the above paradigm is inverted. The high-level components are just abstract classes or interfaces and these are usually (and should be) declared in a package or assembly having no dependency on the code implementing them, and it's the implementation the code that's dependent on higher-level code (because the low-level code must implement a high-level interface or abstract class).

  6. What is the meaning of “inversion” in `Dependency Inversion Design Principle

  7. DIP reduces coupling between different pieces of code.

  8. What is the Dependency Inversion Principle and why is it important?

  9. [P141 HeadFirst] راهکارها

  10. به هیچ کلاس کانکرتی به طور مستقیم اشاره نکنید. متغیرها نباید به کلاس‌های کانکرت اشاره کنند.

  11. از کلاس‌های کانکرت مشتق نگیرید، به جای آن از اینترفیس‌ها و کلاس‌های ابسترکت مشتق بگیرید.

  12. متدی را که در کلاس پایه «پیاده‌سازی» شده است را override نکنید!!

Object-modeling technique

دیاگرام‌های کتاب Gang of for بر مبنای OMT هست: Object-modeling technique OMT object diagram

#الگوی طراحی Builder

تعریف: الگوی طراحی Builder، روند ساخت یک شیء پیچیده را از نمایش آن جدا می‌کند به طوری که یک روند ساخت مشترک می‌تواند برای ساخت انوع نمایش‌ها به کار گرفته شود.

مثال: فرض کنید بخواهیم انواع و اقسام خانه‌ها را طراح کنیم. روند طراحی در تمامی خانه‌ها یکسان است. که به کلاس‌های زیر تقسیم می‌شود:

##Builder

  1. زیربنای آن را ایجاد می‌کنیم.
  2. ساختار و اسکلت آن را ایجاد می‌کنیم.
  3. سقف آن را می‌سازیم.
  4. فضای داخل خانه را طراحی می‌کنیم.

بنابراین برای طراحی همهٔ ساختمان‌ها یک رویهٔ یکسان داریم. بنابراین یک کلاس اینترفیس برای تمامی ساختمان‌ها با ۴ رویهٔ مذکور ایجاد می‌کنیم. که به آن Builder می‌گوییم.

در این مثال: HouseBuilder

ConcreateBuilder

حال به تعداد انواع خانه‌ها، اینترفیس Builder را پیاده‌سازی می‌کنم، در این مثال می‌توانیم خانهٔ خشتی، خانهٔ گلی، خانهٔ برفی، خانهٔ فلزی، خانهٔ فلزی، خانهٔ چوبی، خانهٔ سیمانی را بسازیم. به هر یک از این کلاس‌ها ConcreateBuilder می‌گوییم:

  1. KheshtiBuilder
  2. GeliBuilder
  3. BarfiBuilder
  4. FeleziBuiler

Director

پیمانکار ساختمان، ساختمان‌ها را از طریق اینترفیس House ایجاد می‌کند. (ورودی: یک نوع خانه از نوع HouseBuilder)

  1. ساخت زیربنا
  2. ساخت اسکلت و ساختار ساختمان
  3. ساخت سقف
  4. طراحی درون ساختمان

Product

محصول نهایی، حاصل ترکیب تمامی مراحل ساخت یک خانه است.

  1. خانهٔ گلی
  2. خانهٔ خشتی
  3. خانهٔ سیمانی و ...

Client

HouseBuilder builder = new KheshtiBuilder(); Director director = new Director(builder); director.construct();

بیشتر بخوانید:

  1. http://javapapers.com/design-patterns/builder-pattern/

الگوهای طراحی Factory

  1. Simple Factory (idiom)
  2. Factory Method Pattern
  3. Abstract Factory

نکات:

  1. Factories are used to encapsulate instantiation.
  2. Factory Method vs. Abstract Factory: An Abstract Factory is used to create a family of related products (Factory Method creates one product).

Simple Factory (Idiom)

  1. Simple Factory returns instances of classes that have the same methods. They may be instances of different derived subclasses, or they may in fact be unrelated classes that just share the same interface. Either way, the methods in these class instances are the same and can be used interchangeably.
  2. Simple Factory یک الگوی طراحی واقعی نیست. اما به عنوان یک idiom برنامه‌نویسی بسیار رایج به کار گرفته می‌شود.
  3. وصل کردن کد به کلاس‌های کانکرت، کد را شکننده و غیرقابل انعطاف می‌کند.
  4. جایگزینی اپراتور new با متدهای createConcrete
  5. می‌توانیم از متد استاتیک در این الگو استفاده کنیم.
  6. استفاده از new باعث ایجاد نمونه از کلاس‌های کانکرت می‌شود.
  7. استفاده از new یک نوع برنامه‌نویسی مرتبط با پیاده‌سازی‌ست تا یک برنامه‌نویسی مرتبط به اینترفیس. (کد شکننده، خطا پذیر، غیر قابل انعطاف می‌شود)
  8. کلاس‌های کانکرت معمولاً بیشتر از یک بار یک مکان نمونه‌برداری (Instantiate) می‌شوند.
  9. بنابراین در صورتی که بخواهیم تغییر بدهیم باید تمامی نمونه‌برداری‌ها را در مکان‌های مختلف را تغییر دهیم. که این کار طاقت‌فرسا، سخت و خطاپذیر است.

چرا از Simple Factory استفاده می‌کنیم؟

  1. Multiple Clinets neeeding same types of object
  2. Ensure consistent object initialization.

SimpleFactory Simple Factory Simple Factory Diagram

Keywords:

  1. Depenency
  2. Loose Couple
  3. Concrete classes (When you see new, think concrete)
  4. Encapsulating object creation

مثال

public class PizzaStore {
	SimplePizzaFactory factory;
 
	public PizzaStore(SimplePizzaFactory factory) { 
		this.factory = factory;
	}
 
	public Pizza orderPizza(String type) {
		Pizza pizza;
 
		pizza = factory.createPizza(type);
 
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();

		return pizza;
	}

}
public class SimplePizzaFactory {

		// می‌توانیم این متود را استاتیک تعریف کنیم تا نیازی به ساخت شیء فکتوری نباشد و بتوانیم مستقیما از کلاس این متود را صدا بزنیم.
	public Pizza createPizza(String type) { 
		Pizza pizza = null;

		if (type.equals("cheese")) {
			pizza = new CheesePizza();
		} else if (type.equals("pepperoni")) {
			pizza = new PepperoniPizza();
		} else if (type.equals("clam")) {
			pizza = new ClamPizza();
		} else if (type.equals("veggie")) {
			pizza = new VeggiePizza();
		}
		return pizza;
	}
}

pizza Simple Factory

اطلاعات بیشتر

  1. Simple Factory Pattern Side by Side with Abstract Pattern
  2. Simple Factory
  3. ص ۱۱۹ Head First Design Patterns

الگوی طراحی Factory Method (Virtual Constructor)

  1. The factory method pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate.
  2. Factory Method lets a class deffer instantiation to subclasses.
  3. Eliminates need to bind creation code to specific subclasses.
  4. May need to subclass Creator for each ConcreteProduct
  5. Provides hooks for subclasses.
  6. Connects parallel class hierarchies.
  7. در الگوی طراحی Factory Method از Simple Factory استفاده می‌کنیم.
  8. در Simple Factory تنها یک کارخانه داریم. اما اگر چند کارخانه داشته باشیم که همگی این کارخانه‌ها محصولات مشابهی تولید کنند مثلاً همگی موبایل تولید می‌کنند (اما هر کارخانه پیاده‌سازی خودش را دارد) در چنین حالتی از Factory Method استفاده می‌کنیم. به این صورت یک رابط برای کارخانه‌ها ایجاد می‌کنیم و پیاده‌سازی متود ساخت محصول را به کارخانه‌ها واگذار می‌کنیم. هر یک از کارخانه‌ها از Simple Factory برای تولید محصولاتش استفاده می‌کند.
  9. به روش بالا می گوییم: Allowing the subclasses to decide یا Real-time decision
  10. برای اینکه پارامترهای Concrete Factory بتوانند Type-Safe باشند، می‌توانیم از enum استفاده کنیم و یا روش‌های بهتر.
  11. وقتی که نمونه‌سازی اشیاء را در یک آبجکت یا متد، کپسوله کنیم، باعث بالا رفتن maintenance می‌شود و باعث می‌شود از کدهای اضافی و مجدد خودداری شود.
  12. Dependency Inversion Principle.

ساختار

Factory Method Pattern Factory Method

مثال ۱- ساخت موبایل از دو کارخانهٔ متفاوت

Product (Mobile)

یک واسط برای تمامی موبایل‌ها تعریف می‌کنیم و ویژگی‌ها و رفتارهای مشترک را ذکر می‌کنیم.

  1. نام موبایل
  2. رنگ

ConcreateProduct

واسط موبایل را برای موبایل‌های مختلف پیاده‌سازی می‌کنیم.

  1. Nokia N900
  2. Nokia N95
  3. Motorola Atrix
  4. Motorola A1200

Creator/Factory

واسط کارخانه createMobile()

ConcreteCreator/ConcreteFactry

هر کدام از کارخانه‌ها باید واسط کارخانه را پیاده‌سازی کنند.

  1. NokiaFactory
  2. MotorolaFactory
  3. ...

Client

Factory  factory =  new NokiaFactory()
Car car = factory.createMobile(مشخصات موبایل، نام موبایل، مثل رنگ و ...)

Mobile Factory

بیشتر بخوانید

  1. کلاس SAXParserFactory
  2. http://javapapers.com/design-patterns/factory-method-pattern/
  3. http://stackoverflow.com/questions/9963090/factory-pattern-vs-factorymethod-pattern
  4. http://c2.com/cgi/wiki?FactoryMethodPattern

الگوی طراحی Abstract Factory

  1. اگر چند نوع محصول و چند کارخانهٔ مختلف داشته باشیم از Abstract Factory استفاده می‌کنیم.
  2. The job of an Abstract Factory is to define an interface for creating set of products.

Abstract Factory Abstract Factory 2

مثال

کارخانه‌ها به سه دسته تقسیم می‌شوند (نوکیا/سامسونگ/اچ‌تی‌سی) و محصولات به دو دستهٔ (گوشی‌های هوشمند/گوشی‌های غیرهوشمند) در این مثال ابتدا یک کلاس انتزاعی از کارخانه‌ها می‌سازیم که این کلاس دو متد دارد، یکی ساخت گوشی هوشمند آن کارخانه و دیگری ساخت گوشی غیرهوشمند آن کارخانه.

سپس از کلاس انتزاعی کارخانه، سه کلاس نوکیا و سامسونگ و اچ‌تی‌سی می‌سازیم که هر کدام از این کارخانه‌ها دو نوع گوشی هوشمند و غیر هوشمند خود را می‌سازند.

در این مثال، کلاینت ما از نام گوشی‌ها با خبر نیست. مثلاً نمی‌داند که گوشی هوشمند سامسونگ چیست. کلاینت درخواستش را اعلام می‌کند. مثلاً می‌گوید گوشی هوشمند سامسونگ را می‌خواهم. کلاس کانکرت کارخانهٔ سامسونگ درون کلاس ساخت گوشی هوشمند خود، گالاکسی‌اس۲ را می‌سازد.

متن کامل مثال: http://www.codeproject.com/Articles/331304/Understanding-and-Implementing-Abstract-Factory-Pa

بیشتر بخوانید

  1. Simple Factory vs. Factory Method vs. Abstract Factory
  2. Wikipedia: Abstract factory pattern

الگوی طراحی Singleton

  1. کانستراکتور کلاس را پرایویت می‌کنیم تا کسی نتواند آن کلاس را خارج از کلاس new کند.
  2. داخل کلاس یک متود استاتیک تعریف می‌کنیم و تنها یک نمونه از کلاس تولید می‌کنیم. اگر قبلاً یک نمونه تولید شده بود، همان نمونهٔ قبلی را برمی‌گردانیم.

Multithreading and Singleton

  1. Singleton in multi-threaded environment
  2. lazy initialization
  3. باید این الگو را طوری به کار ببریم که thread safe باشد.

Double-checked locking

در محیط‌های چند نخی، گرفتن و آزاد کردن lock خیلی هزینه‌بر است و ممکن است تعداد این درخواست‌ها خیلی خیلی زیاد شود. برای کاهش سربار lock می‌توان پس از اینکه فلگ را چک کردیم lock کنیم تا سربار کاهش یابد.

  1. Double-checked locking
  2. Double-checked locking and the Singleton pattern
  3. The "Double-Checked Locking is Broken" Declaration

الگوی طراحی Prototype

وقتی که ساخت یک شیئ زمان‌بر و هزینه‌بر باشد. بهتر است به جای این که برای تعداد زیادی از اشیاء تمام مراحل ساخت شیئ را طی کنیم، یک پروتوتایپ می‌سازیم سپس از روی آن نمونه‌برداری می‌کنیم و طبق نیازهای خودمان، اشیاء جدید را اصلاح می‌کنیم. پروتوتایپ: نمونهٔ اولیه، اولین شی‌ای که می‌سازیم و سپس تمامی اشیاء را از روی این شئ می‌سازیم.

مثال: ساختن انواع اقسام خانه‌ها خیلی زمان‌بر است. همهٔ مراحل ساخت این خانه‌ها هم یکسان است. در نتیجه به جای این که هر دفعه که مشتری خانهٔ خاصی (گلی، خشتی، سیمانی و ...) را طلب کرد. از یک نمونهٔ اولیه (پروتوتایپ) که قبلاً ساخته‌ایم یکی فتوکپی می‌گیریم و سپس متناسب با نیاز مشتری آن را تغییر می‌دهیم و به مشتری تحویل می‌دهیم. اینطوری دیگر لازم نیست تمامی مراحل زمان‌بر ساخت خانه را از اول تکرار کنیم. (DRY)

بیشتر بخوانید

  1. http://www.codeproject.com/Articles/42582/Prototype-Design-Pattern

DRY: Do Not Repeat Yourself

الگوی طراحی Singleton

هدف: هر گاه بخواهیم مطمئن شویم که فقط یک نمونه از کلاس می‌تواند وجود داشته باشد، و دسترسی سراسری به آن داشته باشیم، از این الگو استفاده می‌کنیم.

بیشتر بخوانید

  1. http://stackoverflow.com/questions/86582/singleton-how-should-it-be-used
  2. http://www.yolinux.com/TUTORIALS/C++Singleton.html
  3. http://stackoverflow.com/questions/1008019/c-singleton-design-pattern

#الگوی طراحی Adapter هدف: این الگو، اجازه می‌دهد تا دو اینترفیس ناسازگار با یکدیگر کار کنند.

راه‌های پیاده‌سازی:

  1. چندوراثتی: کلاس Adapter، رو رابط Adaptee و Target را پیاده‌سازی می‌کند.
  2. ترکیب شی (Object Composition)؛ کلاس Adapter، رابط Target را پیاده‌سازی می‌کند و درخواست‌های Target را برای Adaptee ترجمه می‌کند.

Target

رابطی‌ست (اینترفیس) که کلاینت از آن استفاده می‌کند.

Client

شیئ‌ای‌ست که با اشیاء‌ای که با Target Interface مطابقت دارند، همکاری می‌کند.

Adaptee

Adapter

یک رابط را به رابط دیگر (متناسب با درخواست کلاینت) تبدیل می‌کند. درخواست کلاینت را می‌گیرد، و آن را برای Adaptee Interface ترجمه می‌کند. این کلاس، رابط Target را پیاده‌سازی می‌کند

بیشتر بخوانید

  1. java.io.InputStreamReader(InputStream)
  2. java.io.OutputStreamWriter(OutputStream)

الگوی طراحی Observer

  1. Publishers + Subscribers = Observer Pattern
  2. Subjects + Observers = Observer Pattern

Keywords:

  1. Loos coupling
  2. one-to-many relationship
  3. minimized interdependency

این الگو زمانی اعمال می‌شود که Subject-ها و Observer-ها Loose Couple باشند.

Components

  1. Subject
  2. Observer
  3. ConcreteSubject
  4. ConcreteObserver

الگوی طراحی Decorator

انعطاف‌پذیری و تغییر رفتار نمونه‌ها، در زمان اجرا.

##keywords

  1. wrapper
  2. aggregation relationship
  3. Open-Closed Principle (Classes should be open for extension, but closed for modification)

Components

  1. Component تعریف اینترفیس و تعریف عملیات لازم.
  2. ConcreteComponent پیاده‌سازی اینترفیس و عملیات.
  3. Decorator این کلاس با کامپوننت، رابطهٔ اگریگیشن دارد و داخل خود، یک نمونه از کامپوننت را نگهداری می‌کند.
  4. ConcreteDecoratorA

مثال ۱

فرض کنید که یک بستنی فروش سه نوع بستنی لیوانی، قیفی و چوبی دارد. این بستنی فروش هنگام فروش هر یک از این بستنی‌ها طبق سلیقهٔ مشتری، بستنی را با عسل، کاکائو، شکلات، بادام و ... تزئین می‌کند.

بیشتر بخوانید

  1. http://javapapers.com/design-patterns/decorator-pattern/ یک مثال خوب و ساده با جاوا
  2. java.io.BufferedReader;
  3. java.io.FileReader;
  4. java.io.Reader;

MVC

MVC بیشتر یک معماری محسوب می‌شود تا یک الگوی طراحی

  1. http://leepoint.net/notes-java/GUI/structure/40mvc.html

Strategy pattern (policy pattern)

در الگوی طراحی استراتژی سعی می‌کنیم که رفتارهای غیرثابت و متفاوت (استراتژی‌های متفاوت) را از کلاس خارج کنیم و به طور مستقل آن‌ها را کپسوله کنیم. در این صورت هر کلاس، هر کدام از الگوریتم‌هایی که نیاز داشته باشند را درون خود استفاده می‌کنند. همچنین این الگو اجازه می‌دهد تا هر یک از کلاس‌ها هر وقت که بخواهند، استراتژی خودشان را تغییر دهند.

Keywords

  1. Behavioral Pattern
  2. Strategy at runtime (Change Behavior at Runtime)
  3. Composition (HAS-A is better than IS-A)

نکات

  1. Strategy lets the algorithm vary independently from clients that use it.
  2. Strategy at runtime (algorithms can be selected at runtime)
  3. انتخاب رفتار و استراتژی مناسب در runtime
  4. رفتارها و استراتژی‌هایی که طول ساختار وراثتی کلاس تغییر می‌کند را مشخص کنید و آن رفتارها را از کلاس خارج کنید. و آن‌ها را جداگانه کپسوله کنید.
  5. Separating What changes from what stays the same.
  6. مزیت استراتژی این است که اگر بخواهیم در طول توسعهٔ نرم‌افزار رفتارها و استراتژی‌های جدیدی تعریف کنیم، نیازی به تغییر کلاس‌های اصلی که از این رفتارهای استفاده می‌کنند نداریم.

Participants

  1. Strategy
  2. ConcreateStrategy
  3. Context

Diagram

StrategyPattern

Client Code

Context context = new Context(new ConcreateStrategy1());
context.AlgorithmInterface();

##مثال ۱ فرض کنید که کلاسی داریم به نام Car() با متودی به نام run() آنگاه می‌توانیم آن را به صورت زیر پیاده کنیم:

Car car = new Car();
car.run();

حالا اگر بخواهیم هنگامی که ماشین روشن است، رفتار ماشین را تغییر دهیم چه کار کنیم؟ مثلاً بخواهیم در نرم‌افزار بازی دکمهٔ Boost‍ را شبیه‌سازی کنیم. چندین روش وجود دارد یکی این که از متغییرهای شرطی و ... استفاده کنیم راه دیگر استفاده از الگوی طراحی استراتژی هست. مثلاً‌ می‌تواین حین بازی موتور میاشین را عوض کنیم!! مثال:

Class Car()
{
    this.motor = new Motor(this) 

    // passing "this" is important for the motor so it knows what it is running

    method run()
    {
        this.motor.run()
    }

    method changeMotor(motor)
    {
        this.motor=motor 
    }

}

مثال ۲

فرض کنید که یک کارخانهٔ تلفن گوشی همراه داریم. که انواع و اقسام گوشی‌ها را تولید می‌کند. خب برای پیاده‌سازی کلاس‌های این گوشی‌ها چه کنیم؟

اولی: آیا می‌توانیم تمامی رفتارهای مختلف و قابلیت‌های گوشی‌های مختلف رو در کلاس مادر تعریف کنیم؟

دومی: خیر، چون همهٔ‌ گوشی‌ها همهٔ قابلیت‌ها را پیاده نمی‌کنند. بعضی از گوشی‌ها دوربین دارند بعضی ندارند. بعضی رادیو دارند بعضی ندارند. بعضی قابلیت اتصال به کامپیوتر دارند و بعضی ندارند.

اولی: خب حالا چه کار کنیم؟

دومی: خب همهٔ قابلیت‌ها را در کلاس مادر تعریف نمی‌کنیم. سعی می‌کنیم قابلیت‌ها را در طول ساختار وراثت به سیستم اعمال کنیم.

اولی: اولاً‌ این روش معقولانه‌ای نیست چون برای اضافه کردن هر رفتار و قابلیت جدید باید کلاس و ساختار وراثت را دچار تغییر کنیم. دوم این که باعث ایجاد کدهای تکراری می‌شود.

دومی: راهکار چیست؟

اولی: استفاده از الگوی استراتژی یعنی رفتارهای متغیر را از رفتارهای ثابت جدا کنیم و رفتارهای متغیر را ساختار وراثتی کلاس خارج کنیم. و آن‌ها را کپسوله کنیم.

اطلاعات بیشتر

  1. How does the Strategy Pattern work?
  2. ص ۳۴۹ کتاب Gang of for
  3. ص ۱۲ کتاب Head First Design Pattern

Model View ViewModel (MVVM)

  1. یک الگوی طراحی نیست. بلکه الگوی معماری است.

Aggregation vs. Composition

![Aggregation vs. Composition]("http://yuml.me/diagram/scruffy;/class/[Simcard]<>-->[SmartPhone], [SmartPhone]++-->[Camera]")

Clone this wiki locally