# الگوهای طراحی در پایتون

در مهندسی نرم‌افزار، الگوی طراحی یک راه‌حل عمومی قابل تکرار برای مشکلات متداول درزمینهٔ طراحی نرم‌افزار است. الگوی طراحی، یک طراحی تمام‌شده نیست که به‌صورت مستقیم بتواند تبدیل به کد منبع یا ماشین شود؛ بلکه، یک توضیح یا قالب برای حل یک مسئله در شرایط مختلف است. الگوها درواقع بهترین روش ممکن هستند که یک برنامه‌نویس می‌تواند در هنگام طراحی یک برنامه برای حل مشکلاتش از آن‌ها استفاده کند. الگوهای طراحی شیءگرا نوعاً نشان‌دهندۀ روابط و تعامل‌ها بین کلاس‌ها و شیء‌ها هستند، بدون این‌که کلاس‌ها یا اشیا نهایی برنامه را مشخص کند. الگوهایی که در خود وضعیت‌های تغییرپذیر دارند، شاید مناسب زبان‌های برنامه‌نویسی تابعی نباشند. هم‌چنین، در بعضی از زبان‌ها که برای حل یک مسئله راه‌حل‌های آمادۀ از پیش تعریف‌شده وجود دارد، استفاده از بعضی الگوها برای حل مسئلۀ مشابه می‌تواند لازم نباشد. به همین ترتیب، الگوهای طراحی شیء‌گرا ممکن است برای زبان‌های غیر شیءگرا مناسب نباشند.\
الگوهای طراحی با توجه به کاربردها و اهدافی که به آن منظور ارائه‌شده‌اند، به سه دسته عمومی تقسیم می-شوند

* الگوهای ایجادی
* الگوهای ساختاری
* الگوهای رفتاری

که در هریک از آن‌ها سعی می‌کنیم مهم‌ترینشان را به‌اختصار توضیح دهیم.

## الگوهای ایجادی

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

### Singleton

این الگو ایجاد شیء از یک کلاس را محدود می‌سازد. این الگو زمانی مفید است که در سرتاسر سیستم تنها به یک نمونه از آن کلاس نیاز باشد. این مفهوم عموماً به سیستم‌هایی که با یک یا تعداد محدودی نمونه بهینه‌تر کار می‌کنند، نیز تعمیم داده می‌شود. واژه آن از مفهوم ریاضی یگانه (Singleton) برگرفته‌شده است.

#### مثال در دنیای واقعی

الگوی Singleton تضمین می‌کند که از هر کلاس یک کلاس فقط یک نمونه داشته باشد و یک نقطه دسترسی جهانی به آن نمونه را فراهم می‌کند. دفتر رئیس‌جمهور یک Singleton است. قانون اساسی روش‌های انتخاب رئیس‌جمهور را مشخص می‌کند، مدت تصدی مقام را محدود می‌کند و ترتیب جانشینی را مشخص می‌کند. درنتیجه، حداکثر یک رئیس‌جمهور فعال در هر زمان مشخص وجود دارد. صرف‌نظر از هویت شخصی رئیس‌جمهور فعال، عنوان رئیس‌جمهور» یک نقطه دسترسی جهانی است که یک فرد را در دفتر ریاست جمهوری مشخص می‌کند.

![](/files/-MH_KH7mqETzrCmdLiqa)

#### روش پیاده سازی الگوی طراحی singleton

نحوه پیاده‌سازی این الگو به‌صورت کلی به این گونه است که کلاس باید یک تابع داشته باشد تا یک شی از آن کلاس را درصورتی‌که قبلا ساخته نشده است، بسازد.\
&#x20;برای اطمینان از اینکه نمونه دیگری از این کلاس قابل ایجاد نباشد باید دسترسی به Constructor کلاس را به‌صورت Private تعریف کنیم. مراحل پیاده سازی سینگلتون عبارت‌اند از :

1. اضافه کردن یک متغیر Static از نوع Private به کلاس موردنظر به منظور ذخیره‌سازی نمونه Singleton در آن.
2. نوشتن یک تابع Static از نوع Public برای دریافت نمونه ساخته شده Singleton (این تابع ورودی نخواهد داشت).
3. &#x20;پیاده‌سازی "مقدار‌دهی اولیه" متغیر در داخل تابع Static نوشته‌شده است. در این مرحله باید یک شی جدید در اولین فراخوانی ایجاد شود و مقدار آن را در متغیر Static قرار دهد. این تابع در فراخوانی‌های بعدی باید شی ایجادشده را فراخوانی کند.
4. &#x20;باید Constructor مربوط به کلاس و کلاسی که از آن ارث بری شده است را Private کنیم. پس از این کار دیگر قادر نخواهیم بود در خارج از کلاس، از آن شی نمونه ای بسازیم و این کار فقط در همان کلاس امکان‌پذیر است.
5. در نهایت باید در کدهای خود به‌جای فراخوانی مستقیم Constructor سینگلتون (Direct calls) از تابع Static که نوشته‌ایم به این منظور استفاده کنیم.

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Ensure a class only has one instance, and provide a global point of
access to it.
"""
class Singleton(type):
    """
    Define an Instance operation that lets clients access its unique
    instance.
    """
    def __init__(cls, name, bases, attrs, **kwargs):
        super().__init__(name, bases, attrs)
        cls._instance = None

    def __call__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__call__(*args, **kwargs)
        return cls._instance

class MyClass(metaclass=Singleton):
    """
    Example class.
    """
    pass

def main():
    m1 = MyClass()
    m2 = MyClass()
    assert m1 is m2

if __name__ == "__main__":
    main()


```

### Abstract factory

الگوی کارخانه انتزاعی ، در الگوهای نرم‌افزاری روشی برای جمع‌بندی گروهی از کارخانه‌های مجازی است که ساختار مشابهی دارند ولی از کلاس‌های مختلفی تشکیل‌شده‌اند.\
&#x20;در حالت عادی، برنامه زیرشاخه یک ساختار یکپارچه از کارخانه انتزاعی را می‌سازد و سپس از واسط کاربری می‌خواهد که شیءهای مختلفی در آن (دارای شباهت در تعدادی از ویژگی‎ها) بسازد. برنامه زیرشاخه نمی‌داند (یا اهمیت نمی‌دهد) که چه شیءای را از کتابخانه گرفته است. چون تنها از شی‌ء ساخته‌شده استفاده می‌کند. این الگو جزییات اجرا و استفاده از گروهی از اشیاء را، از نحوه پیاده‌سازی آن‌ها جدا می‌کند. چراکه ساخت اشیاء در کارخانه صورت می‌گیرد. ماهیت کارخانه انتزاعی را می‌توان این‌طور تعریف کرد که رابطی برای ساخت خانواده‌ای از اشیاء مرتبط یا وابسته بدون نیاز به مشخص کردن نوع کلاس آن‌ها.

#### مثال در دنیای واقعی

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

![](/files/-MH_K9wFttk5bwUqFFJ3)

#### روش پیاده سازی الگوی طراحی Abstract Factory

در این بخش به بررسی مراحل پیاده‌ سازی الگوی طراحی کارخانه انتزاعی می‌پردازیم. مراحل پیاده سازی این الگو عبارت‌اند از :

1. &#x20;ابتدا باید فهرستی از انواع اشیای موردنظر در نرم افزار تهیه شود.
2. &#x20;باید برای هر یک از انواع آن‌ها یک Interface تعریف شود. سپس تمام کلاس‌های این اشیا باید از این Interfaceها پیروی کنند.
3. &#x20;در این گام Interface کارخانه انتزاعی باید ایجاد شود. در این Interface مجموعه ای از روش‌های ایجاد اشیا انتزاعی تعریف می‌شود.
4. &#x20;باید برای هر یک از اشیا که سبک مشابهی دارند کلاس‌های به‌عنوان کارخانه سازنده آن‌ها ایجاد شود. این کارخانه‌ها که اشیا مرتبط را تولید می‌کنند باید از Interface کارخانه انتزاعی پیروی کنند.
5. &#x20;کد مربوط به راه اندازی کارخانه را در نرم افزار باید نوشت. این کد باید یک کلاس کارخانه مرتبط را بسته باشد، بسته به پیکربندی برنامه یا محیط فعلی. این کارخانه را به کلیه کلاس هایی که محصولات را طراحی می‌کنند انتقال دهید.
6. هر جایی در کدهای نرم افزار که اشیا به‌صورت مستقیم ایجادشده اند، باید شناسایی شود. سپس آن‌ها با توابع ساخت مناسب با توجه به کارخانه مربوطه جایگزین شوند.

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Provide an interface for creating families of related or dependent
objects without specifying their concrete classes.
"""
import abc

class AbstractFactory(metaclass=abc.ABCMeta):
    """
    Declare an interface for operations that create abstract product
    objects.
    """
    @abc.abstractmethod
    def create_product_a(self):
        pass

    @abc.abstractmethod
    def create_product_b(self):
        pass

class ConcreteFactory1(AbstractFactory):
    """
    Implement the operations to create concrete product objects.
    """
    def create_product_a(self):
        return ConcreteProductA1()

    def create_product_b(self):
        return ConcreteProductB1()

class ConcreteFactory2(AbstractFactory):
    """
    Implement the operations to create concrete product objects.
    """
    def create_product_a(self):
        return ConcreteProductA2()

    def create_product_b(self):
        return ConcreteProductB2()

class AbstractProductA(metaclass=abc.ABCMeta):
    """
    Declare an interface for a type of product object.
    """
    @abc.abstractmethod
    def interface_a(self):
        pass

class ConcreteProductA1(AbstractProductA):
    """
    Define a product object to be created by the corresponding concrete
    factory.
    Implement the AbstractProduct interface.
    """
    def interface_a(self):
        pass

class ConcreteProductA2(AbstractProductA):
    """
    Define a product object to be created by the corresponding concrete
    factory.
    Implement the AbstractProduct interface.
    """
    def interface_a(self):
        pass


class AbstractProductB(metaclass=abc.ABCMeta):
    """
    Declare an interface for a type of product object.
    """
    @abc.abstractmethod
    def interface_b(self):
        pass

class ConcreteProductB1(AbstractProductB):
    """
    Define a product object to be created by the corresponding concrete
    factory.
    Implement the AbstractProduct interface.
    """
    def interface_b(self):
        pass

class ConcreteProductB2(AbstractProductB):
    """
    Define a product object to be created by the corresponding concrete
    factory.
    Implement the AbstractProduct interface.
    """
    def interface_b(self):
        pass

def main():
    for factory in (ConcreteFactory1(), ConcreteFactory2()):
        product_a = factory.create_product_a()
        product_b = factory.create_product_b()
        product_a.interface_a()
        product_b.interface_b()

if __name__ == "__main__":
    main()


```

### Builder

الگوی سازنده یک الگوی مهندسی نرم‌افزار به‌منظور ایجاد اشیا است. این الگو برخلاف الگوی کارخانه انتزاعی ( abstract factory pattern) و الگوی روش کارخانه ( factory method pattern) که به‌منظور رعایت پدیدۀ چندریختی ( polymorphism) ایجادشده‌اند به‌منظور حل وجهۀ دیگری از مشکل ساخت و تنظیم اشیا در برنامه‌نویسی معرفی‌شده است. مشکل بدین شرح است که گاهی نیاز است هنگام ساخت یک شی‌ء تعداد زیادی پارامتر را به سازندۀ ( constructor) آن تحویل دهیم و این کار خوانایی برنامه را کم می‌کند. به‌منظور حل این مشکل از الگوی سازنده استفاده می‌کنیم. در این الگو به‌جای طراحی تعدادی سازنده ( constructor) با تعداد زیادی پارامتر، از یک شی‌ء دیگر استفاده می‌کنیم که کار پارامتر دهی را به‌صورت مرحله‌به‌مرحله و خواناتر انجام می‌دهد و درنهایت از نوع شی‌ء موردنظر یک نمونه با تنظیمات خواسته‌شده به ما تحویل می‌دهد.

معمولاً یک طراح در سیر طراحی ابتدا با الگوی روش کارخانه ( factory method) شروع می‌کند سپس به الگوی کارخانه انتزاعی ( abstract factory) یا الگوی نمونه اولیه ( prototype) یا سازنده ( builder) متوسل می‌شود. معمولاً هنگامی به الگوی سازنده متوسل می‌شویم که در فرایند طراحی به انعطاف‌پذیری بیشتر نیاز پیدا می‌کنیم. نیت استفاده از این الگو این است که فرایند ساخت ( construction) یک شی‌ء پیچیده را از کد آن شی‌ء ( object representation) جدا کنیم.

#### مثال در دنیای واقعی

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

![](/files/-MH_LId6LDElD4zH01un)

#### روش پیاده سازی الگوی طراحی Builder

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

1. &#x20;ابتدا باید از این موضوع اطمینان حاصل شود که به‌طور واضح و دقیق تمام اقدامات و مراحل لازم برای ساخت تمامی نمونه های شی موردنظر (محصول) تعریف شده باشند. در غیر این صورت پیاده سازی این الگوی طراحی امکان پذیر نخواهد بود.
2. &#x20;سپس این مراحل باید در یک Interface بانام Builder تعریف شوند.
3. &#x20;در سومین گام باید یک کلاس Builder برای هر یک از نمونه‌های شی موردنظر ایجاد شود. این کلاس‌ها باید Interface ساخته شده در گام قبلی را Implement کنند. به عبارتی دیگر همه آن‌ها باید از مراحل ساخت و ساز تعریف شده پیروی کنند.
4. &#x20;همچنین می‌توان از کلاس دیگری به نام Director برای مدیریت و پیاده سازی مراحل قبل استفاده کرد. این کلاس می تواند از راه‌های مختلفی به ساخت اشیا با استفاده از همان Builderها بپردازد.
5. بنابراین ابتدا باید کلاس های Director و Builder ایجاد شوند. سپس باید قبل از اینکه عملیات ساخت شی آغاز شود، کلاس Builder به کلاس Director مرتبط شود. این ارتباط یک بار به وسیله ارسال پارامترهای کلاس Builder در Constructor کلاس Director ایجاد می‌شود. با این کار کلاس Director در ساخت و سازهای بعدی از Builder استفاده می‌کند. البته برای این منظور یک راه حل جایگزین نیز وجود دارد. در راه حل دوم می‌توان Builderها را به‌صورت مستقیم در تابعی (Method) که وظیفه ساخت در کلاس Director را دارد، وارد کنید.
6. در نهایت اگر تمام اشیا از همان Interface پیروی کنند می‌توان نتایج ساخت و ساز را به‌صورت مستقیم از کلاس Director دریافت کرد. در غیر این صورت باید نتایج از همان کلاس Builder دریافت شوند.

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Separate the construction of a complex object from its representation so
that the same construction process can create different representations.
"""

import abc

class Director:
    """
    Construct an object using the Builder interface.
    """
    def __init__(self):
        self._builder = None

    def construct(self, builder):
        self._builder = builder
        self._builder._build_part_a()
        self._builder._build_part_b()
        self._builder._build_part_c()

class Builder(metaclass=abc.ABCMeta):
    """
    Specify an abstract interface for creating parts of a Product
    object.
    """
    def __init__(self):
        self.product = Product()

    @abc.abstractmethod
    def _build_part_a(self):
        pass

    @abc.abstractmethod
    def _build_part_b(self):
        pass

    @abc.abstractmethod
    def _build_part_c(self):
        pass

class ConcreteBuilder(Builder):
    """
    Construct and assemble parts of the product by implementing the
    Builder interface.
    Define and keep track of the representation it creates.
    Provide an interface for retrieving the product.
    """
    def _build_part_a(self):
        pass

    def _build_part_b(self):
        pass

    def _build_part_c(self):
        pass

class Product:
    """
    Represent the complex object under construction.
    """
    pass

def main():
    concrete_builder = ConcreteBuilder()
    director = Director()
    director.construct(concrete_builder)
    product = concrete_builder.product

if __name__ == "__main__":
    main()

```

### Factory

الگوی کارخانه شئ یکی از الگوهای طراحی برنامه‌نویسی شئ‌گرا برای پیاده‌سازی مفهوم کارخانه‌ها است؛ مانند سایر الگوهای سازندگی، کارخانه شئ با مشکل ایجاد اشیاء (محصولات) بدون مشخص کردن کلاس اشیاء خاصی است که قرار است ساخته شوند. اساس الگوی متد کارخانه «تعریف یک رابط برای ایجاد اشیاء که اجازه می‌دهد اشیایی که آن رابط را پیاده‌سازی می‌کنند در رابطه بااینکه کدام کلاس باید ایجاد شود تصمیم بگیرند. متد الگوی کارخانه اجازه می‌دهد که یک کلاس تصمیم در رابطه با ایجاد اشیاء را به زیرکلاس‌ها واگذار نماید.» است.

اساساً کاربرد الگوی کارخانه برای شرایطی است که چندین کلاس با ریشه مشترک داریم (یعنی چندین کلاس یک کلاس فوقانی را پیاده‌سازی می‌کنند) و غالب استفاده نیز با شی‌ء سازی (نمونه‌سازی) از کلاس فوقانی صورت می‌گیرد.

#### مثال در دنیای واقعی

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

![](/files/-MH_M6Xp8MFeossdRCRO)

#### مراحل پیاده سازی الگوی طراحی Factory

در این بخش به بررسی مراحل پیاده‌ سازی الگوی طراحی Factory می‌پردازیم، مراحل پیاده سازی این الگو عبارت‌اند از :

1. &#x20;ابتدا باید یک Interface تعریف کنیم که در آن توابعی تعریف شود که در همه اشیا مشترک و کاربردی است. سپس تمام اشیا باید از یک Interface پیروی کنند.
2. &#x20;باید یک تابع به‌عنوان کارخانه سازنده (Factory) آن شی در کلاسش اضافه شود. نوع متغیری که این تابع Return می‌کند باید با Interface که در بخش قبل ساخته شد، مطابقت داشته باشد.
3. &#x20;در کدهای نوشته‌شده هرجایی که اشیا توسط روش سنتی (به وسیله کیورد new) ایجادشده اند باید پیدا شوند و برای ساخت آن‌ها از تابع کارخانه سازنده آن‌ها استفاده شود.
4. &#x20;باید مجموعه ای از کلاس‌های فرزند سازنده (creator) برای انواع اشیایی که کارخانه می‌سازد، تعریف شوند. سپس در این کلاس ها باید تابع کارخانه بازنویسی (Override) شود تا اصولی که در این تابع تعریف شده اند، به شکل مورد نیاز تغییر داده شوند. مثلا اگر در نحوه ساخت یک خودروی سواری و خودروی باربری تفاوتی وجود دارد، در کلاس‌های مربوط به خود این موضوع در نظر گرفته شود.
5. &#x20;اگر انواع مختلف و زیادی از اشیا وجود دارند که از نظر شما ساختن کلاس‌های فرزند برای همه آن‌ها منطقی به نظر نمی‌رسد و دارای ویژگی‌های مشترکی هستند، می‌توانید آن ویژگی را در کلاس والد وارد کنید و از تعریف مکرر آن در کلاس‌های فرزند خودداری کنید.
6. &#x20;اگر مشاهده کردید میان اشیای ساخته شده توسط تابع کارخانه هیچ ویژگی مشترکی وجود ندارد و تابع کارخانه خالی مانده است، می‌توانید آن را به‌صورت abstract تعریف کنید. همچنین اگر خلاف این امر صادق بود و ویژگی در این تابع باقی ماند، آن ویژگی را می‌توان، یک ویژگی پیشفرض برای اشیا در نظر گرفت.

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Define an interface for creating an object, but let subclasses decide
which class to instantiate. Factory Method lets a class defer
instantiation to subclasses.
"""
import abc

class Creator(metaclass=abc.ABCMeta):
    """
    Declare the factory method, which returns an object of type Product.
    Creator may also define a default implementation of the factory
    method that returns a default ConcreteProduct object.
    Call the factory method to create a Product object.
    """
    def __init__(self):
        self.product = self._factory_method()

    @abc.abstractmethod
    def _factory_method(self):
        pass

    def some_operation(self):
        self.product.interface()


class ConcreteCreator1(Creator):
    """
    Override the factory method to return an instance of a  ConcreteProduct1.
    """
    def _factory_method(self):
        return ConcreteProduct1()


class ConcreteCreator2(Creator):
    """
    Override the factory method to return an instance of a
    ConcreteProduct2.
    """
    def _factory_method(self):
        return ConcreteProduct2()


class Product(metaclass=abc.ABCMeta):
    """
    Define the interface of objects the factory method creates.
    """
    @abc.abstractmethod
    def interface(self):
        pass


class ConcreteProduct1(Product):
    """
    Implement the Product interface.
    """
    def interface(self):
        pass
class ConcreteProduct2(Product):
    """
    Implement the Product interface.
    """
    def interface(self):
        pass


def main():
    concrete_creator = ConcreteCreator1()
    concrete_creator.product.interface()
    concrete_creator.some_operation()


if __name__ == "__main__":
    main()

```

### Prototype

الگوی نمونه اولیه یکی از الگوهای طراحی در توسعه نرم‌افزار است. وقتی نوع اشیاء ساخته شونده با یک نمونه اولیه مشخص شود، از این الگو استفاده‌شده است؛ که درواقع یک مورد مشابه از خودساخته است یا به‌اصطلاح خودسازی کرده است. موارد استفاده از این الگو:

* جلوگیری از وجود کلاس فرزند از یک کلاس سازنده اشیاء در نرم‌افزار مشتری همان‌طوری که الگوی کارخانه انتزاعی عمل می‌کند.
* جلوگیری از هزینه وراثتی ساخت شیء جدید درروش معمول آن (به‌عنوان‌مثال با استفاده از دستور 'new') چراکه در برنامه‌ها این کار ازنظر پردازشی پرهزینه خواهد بود.

#### مثال در دنیای واقعی

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

![](/files/-MH_NzBIB3qDtiL2n7Lt)

#### پیاده سازی الگوی طراحی Prototype

در این بخش به بررسی مراحل پیاده‌ سازی الگوی طراحی نمونه اولیه می‌پردازیم، مراحل پیاده سازی این الگو عبارت‌اند از :

1. &#x20;ابتدا باید یک Interface تعریف شود. سپس در آن یک تابع تحت عنوان Clone ایجاد گردد. سپس کلاس‌های موردنظر باید از این Interface پیروی کنند و تابع Clone را پیاده سازی کنند. این گام برای قانونمند ساختن نرم افزار استفاده می‌شود و در صورت تشخیص می‌توان از آن صرف نظر کرد.
2. &#x20;سپس در کلاس نمونه اولیه باید از یک متد Constructor جدید به نام Clone تعریف شود. این Constructor وظیفه دارد مقادیر پارامترهای تعریف شده در کلاس را از شی اصلی دریافت کند و به نمونه جدید ساخته شده، منتقل سازد.

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Specify the kinds of objects to create using a prototypical instance,
and create new objects by copying this prototype.
"""
import copy

class Prototype:
    """
    Example class to be copied.
    """
    pass


def main():
    prototype = Prototype()
    prototype_copy = copy.deepcopy(prototype)

if __name__ == "__main__":
    main()


```

## الگوهای ساختاری

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

### Adapter

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

#### مثال در دنیای واقعی

الگوی آداپتور اجازه می‌دهد تا با تبدیل واسط یک کلاس به یک رابط مورد انتظار مشتری، کلاس‌های ناسازگار با یکدیگر کار کنند. آچار سوکت نمونه‌ای از آداپتور را ارائه می‌دهد. یک سوکت به یک چرخ‌دستی وصل می‌شود به‌شرط آنکه اندازه درایو یکسان باشد. اندازه معمولی درایو 1/2 و 1/4 است. بدیهی است، یک گیربکس درایو 1/2 اینچی در سوکت درایو 1/4 اینچ جای نمی‌گیرد مگر اینکه از آداپتور استفاده شود. یک آداپتور 1/2 تا 1/4 اینچ دارای یک اتصال زن 1/2 اینچی برای قرار گرفتن در قسمت درایو 1/2 اینچی و یک اتصال نری 1/4 اینچی برای قرار گرفتن در سوکت درایو 1/4 است.

![](/files/-MH_OfnBIE-X0trKnv1o)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Convert the interface of a class into another interface clients expect.
Adapter lets classes work together that couldn't otherwise because of
incompatible interfaces.
"""
import abc

class Target(metaclass=abc.ABCMeta):
    """
    Define the domain-specific interface that Client uses.
    """
    def __init__(self):
        self._adaptee = Adaptee()

    @abc.abstractmethod
    def request(self):
        pass

class Adapter(Target):
    """
    Adapt the interface of Adaptee to the Target interface.
    """
    def request(self):
        self._adaptee.specific_request()

class Adaptee:
    """
    Define an existing interface that needs adapting.
    """
    def specific_request(self):
        pass

def main():
    adapter = Adapter()
    adapter.request()

if __name__ == "__main__":
    main()


```

### Bridge

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

#### مثال در دنیای واقعی

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

![](/files/-MH_OwiHKQg2G89CLdGl)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Decouple an abstraction from its implementation so that the two can vary
independently.
"""
import abc

class Abstraction:
    """
    Define the abstraction's interface.
    Maintain a reference to an object of type Implementor.
    """
    def __init__(self, imp):
        self._imp = imp

    def operation(self):
        self._imp.operation_imp()

class Implementor(metaclass=abc.ABCMeta):
    """
    Define the interface for implementation classes. This interface
    doesn't have to correspond exactly to Abstraction's interface; in
    fact the two interfaces can be quite different. Typically the
    Implementor interface provides only primitive operations, and
    Abstraction defines higher-level operations based on these
    primitives.
    """
    @abc.abstractmethod
    def operation_imp(self):
        pass

class ConcreteImplementorA(Implementor):
    """
    Implement the Implementor interface and define its concrete
    implementation.
    """
    def operation_imp(self):
        pass

class ConcreteImplementorB(Implementor):
    """
    Implement the Implementor interface and define its concrete
    implementation.
    """
    def operation_imp(self):
        pass

def main():
    concrete_implementor_a = ConcreteImplementorA()
    abstraction = Abstraction(concrete_implementor_a)
    abstraction.operation()

if __name__ == "__main__":
    main()


```

### Decorator

در برنامه‌نویسی شئ گرا، الگوی آذین گر یا دکوراتر یک الگوی طراحی است که امکان افزودن رفتار (behavior) به یک شئ را به‌طور پویا یا ایستا فراهم می‌سازد بی‌آنکه رفتار اشیاء دیگر از همان کلاس (که شئ موردبحث از آن ساخته‌شده) دست‌خوش تغییر شوند. الگوی طراحی آذین گر معمولاً برای پایبندی به‌قاعده تک‌وظیفه‌ای مورداستفاده قرار می‌گیرد چراکه این الگوی طراحی، امکان تقسیم عملکردها (functionality) بین کلاس‌های مختلف که هرکدام دغدغه‌های (concern) خاص را پوشش می‌دهند، فراهم می‌سازد.

#### مثال در دنیای واقعی

دکوراتور به‌طور پویا مسئولیت‌های اضافی را به یک شی‌ء متصل می‌کند. تزئیناتی که به درختان کاج یا صنوبر اضافه‌شده نمونه‌هایی از دکوراتورها هستند. چراغ‌ها، گلدان‌ها، نی‌های شیرینی، تزئینات شیشه‌ای و غیره را می‌توان به درخت اضافه کرد تا جلوه‌ای تزئینی به آن بخشیده باشد. تزئینات خود درخت را تغییر نمی‌دهند و بدون توجه به تزئینات خاص مورداستفاده، به‌عنوان یک درخت کریسمس قابل‌تشخیص است. به‌عنوان نمونه‌ای از قابلیت‌های اضافی، اضافه کردن چراغ‌ها به شخص اجازه می‌دهد تا یک درخت کریسمس را روشن کند.\
مثال دیگر: تفنگ حمله به‌خودی‌خود یک اسلحه کشنده است؛ اما می‌توانید از "تزئینات" خاصی استفاده کنید تا آن را دقیق‌تر، ساکت و ویرانگر کنید.

![](/files/-MH_PF1sVutwtBB4yFat)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Attach additional responsibilities to an object dynamically. Decorators
provide a flexible alternative to subclassing for extending
functionality.
"""
import abc

class Component(metaclass=abc.ABCMeta):
    """
    Define the interface for objects that can have responsibilities
    added to them dynamically.
    """
    @abc.abstractmethod
    def operation(self):
        pass

class Decorator(Component, metaclass=abc.ABCMeta):
    """
    Maintain a reference to a Component object and define an interface
    that conforms to Component's interface.
    """
    def __init__(self, component):
        self._component = component

    @abc.abstractmethod
    def operation(self):
        pass

class ConcreteDecoratorA(Decorator):
    """
    Add responsibilities to the component.
    """
    def operation(self):
        # ...
        self._component.operation()
        # ...

class ConcreteDecoratorB(Decorator):
    """
    Add responsibilities to the component.
    """
    def operation(self):
        # ...
        self._component.operation()
        # ...

class ConcreteComponent(Component):
    """
    Define an object to which additional responsibilities can be
    attached.
    """
    def operation(self):
        pass
def main():
    concrete_component = ConcreteComponent()
    concrete_decorator_a = ConcreteDecoratorA(concrete_component)
    concrete_decorator_b = ConcreteDecoratorB(concrete_decorator_a)
    concrete_decorator_b.operation()

if __name__ == "__main__":
    main()

```

### Facade

الگوی نما ، یک الگوی ساختاری در الگوهای طراحی نرم‌افزار است که معمولاً در برنامه‌نویسی شی‌ءگرا از آن استفاده می‌شود. نام آن برگرفته از شباهت آن به مشابه آن در معماری ساختمان نما (ساختمان) است.

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

* استفاده از یک کتابخانه نرم‌افزاری را آسان‌تر کند، بفهمد و آن را تست کند. چراکه توابع راحتی برای عملیات عادی دارد.
* &#x20;به دلایل مشابهی، خواندن از کتابخانه را راحت‌تر و امکان‌پذیرتر می‌کند.
* &#x20;کاهش وابستگی به کدهای خارجی مهم‌ترین وظیفه‌یک کتابخانه داخلی است، چراکه بیشتر قسمت‌های کد از نما استفاده می‌کنند، باعث تغییرپذیری بیشتر در طراحی سیستم می‌شود.
* &#x20;بسته مجموعه‌ای از رابط‌های برنامه کاربری با طراحی ضعیف، تنها با یک رابط برنامه کاربری (API) که از طراحی خوبی برخوردار است.

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

#### مثال در دنیای واقعی

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

![](/files/-MH_Pe4gr40mxHie8m_M)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Provide a unified interface to a set of interfaces in a subsystem.
Facade defines a higher-level interface that makes the subsystem easier
to use.
"""

class Facade:
    """
    Know which subsystem classes are responsible for a request.
    Delegate client requests to appropriate subsystem objects.
    """
    def __init__(self):
        self._subsystem_1 = Subsystem1()
        self._subsystem_2 = Subsystem2()

    def operation(self):
        self._subsystem_1.operation1()
        self._subsystem_1.operation2()
        self._subsystem_2.operation1()
        self._subsystem_2.operation2()

class Subsystem1:
    """
    Implement subsystem functionality.
    Handle work assigned by the Facade object.
    Have no knowledge of the facade; that is, they keep no references to
    it.
    """
    def operation1(self):
        pass

    def operation2(self):
        pass

class Subsystem2:
    """
    Implement subsystem functionality.
    Handle work assigned by the Facade object.
    Have no knowledge of the facade; that is, they keep no references to
    it.
    """
    def operation1(self):
        pass

    def operation2(self):
        pass

def main():
    facade = Facade()
    facade.operation()

if __name__ == "__main__":
    main()


```

### Proxy

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

#### مثال در دنیای واقعی

الگوی وکالت یک نگهدارندِ یا یک مکان را برای دسترسی به یک شی‌ء فراهم می‌کند. چک یا پیش‌نویس بانکی وکالت برای بودجه در یک حساب است. از چک می‌توان به‌جای پول برای انجام خرید استفاده کرد و درنهایت دسترسی به پول نقد را در حساب صادرکننده کنترل کرد.

![](/files/-MH_QFL85eYV3Qd8y3of)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Provide a surrogate or placeholder for another object to control access
to it or add other responsibilities.
"""
import abc

class Subject(metaclass=abc.ABCMeta):
    """
    Define the common interface for RealSubject and Proxy so that a
    Proxy can be used anywhere a RealSubject is expected.
    """
    @abc.abstractmethod
    def request(self):
        pass

class Proxy(Subject):
    """
    Maintain a reference that lets the proxy access the real subject.
    Provide an interface identical to Subject's.
    """
    def __init__(self, real_subject):
        self._real_subject = real_subject

    def request(self):
        # ...
        self._real_subject.request()
        # ...

class RealSubject(Subject):
    """
    Define the real object that the proxy represents.
    """
    def request(self):
        pass

def main():
    real_subject = RealSubject()
    proxy = Proxy(real_subject)
    proxy.request()

if __name__ == "__main__":
    main()


```

## الگوهای رفتاری

الگوهای طراحی رفتاری یا Behavioral مجموعه‌ای از راهکارهای کد نویسی مربوط به تعامل و ارتباط اشیا هستند. این الگوهای طراحی عبارت‌اند از:

### Chain of responsibility

کار این الگوی طراحی به این صورت است که وقتی یک request دریافت می‌شود می‌تواند بر اساس نوع آن request سناریوهای مختلفی جهت پردازش آن request وجود داشته باشد.

تعریفی که Gang of Four از این الگوی طراحی کرده است به‌صورت زیر است:”اجتناب از وابستگی بین فرستنده Request و دریافت‌کننده آن با ایجاد قابلیت رسیدگی به Request توسط شی‌ءها و سناریوهای های مختلف ”.

در این الگو زنجیره request را دریافت کرده و سپس این Request رابین Chain (حلقه) های مختلف ارسال می‌کند تا زمانی که یک chain این درخواست رو پردازش کند و هنگامی‌که این درخواست توسط یکی از Chain ها پردازش شود ارسال متوقف می‌شود. در حقیقت Request وارد Chain های مختلف می‌شود و در زنجیره حرکت می‌کند. زمانی که یک زنجیره قابلیت پردازش این Request را داشته باشد حرکت Request بین زنجیره‌های مختلف متوقف می‌شود.

نقش‌های شرکت‌کننده در این الگوی طراحی موارد زیر است:

1. &#x20;Handler: یک Interface است که signature متد handleRequest را تعریف می‌کند. (signature یک متد در شامل نام متد وردی و خروجی متد است. دقیقاً اتفاقی که در یک interface یا یک متد Abstarct می‌افتد) و همچنین امکان set کردن successor را نیز در این کلاس دیده‌شده است.
2. &#x20;handler: که از کلاس Handler ارث می‌برد و وظیفه پیاده‌سازی متد handleRequest را دارد و همچنین به successor نیز دسترسی دارد. اگر یک Concrete Handler نتواند یک request را handle کند آن request را از طریق Successor به Handler دیگری ارسال می‌کند.
3. &#x20;Client: وظیفه ارسال request به یک Concrete handler را دارد.

#### مثال در دنیای واقعی

الگوی زنجیره‌ای از مسئولیت با قرار دادن بیش از یک موضوع برای رسیدگی به درخواست، از اتصال فرستنده درخواست به گیرنده جلوگیری می‌کند. دستگاه خودپرداز از مکانیسم دادن پول از زنجیره مسئولیت استفاده می‌کند.

![](/files/-MH_U1zRK-LVZ4_ZgPeS)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Avoid coupling the sender of a request to its receiver by giving
more than one object a chance to handle the request. Chain the receiving
objects and pass the request along the chain until an object handles it.
"""
import abc

class Handler(metaclass=abc.ABCMeta):
    """
    Define an interface for handling requests.
    Implement the successor link.
    """
    def __init__(self, successor=None):
        self._successor = successor

    @abc.abstractmethod
    def handle_request(self):
        pass

class ConcreteHandler1(Handler):
    """
    Handle request, otherwise forward it to the successor.
    """
    def handle_request(self):
        if True:  # if can_handle:
            pass
        elif self._successor is not None:
            self._successor.handle_request()

class ConcreteHandler2(Handler):
    """
    Handle request, otherwise forward it to the successor.
    """
    def handle_request(self):
        if False:  # if can_handle:
            pass
        elif self._successor is not None:
            self._successor.handle_request()

def main():
    concrete_handler_1 = ConcreteHandler1()
    concrete_handler_2 = ConcreteHandler2(concrete_handler_1)
    concrete_handler_2.handle_request()

if __name__ == "__main__":
    main()

```

### Command

با استبا استفاده از این الگوی طراحی می‌توانیم فراخوانی یا Call کردن یک متد را بسته‌بندی (Encapsulate) کنیم که این کار فواید زیادی دارد.

قبل از شروع توضیح این الگو نیاز داریم که کمی راجع به Encapsulation یا بسته‌بندی سازی در برنامه‌نویسی شی‌ءگرا باهم صحبت کنیم.

به زبان ساده Encapsulation یا بسته‌بندی سازی به معنی از دسترس خارج کردن جزئیات داخلی که موردنیاز نیست از کاربر است. به‌طور مثال در دنیای واقعی وقتی ما یک دارویی که به شکل کپسول است را خریداری می‌کنیم ما به جزئیات داخلی آن دسترسی نداریم و ما فقط با قورت می‌توانیم از آن استفاده کنیم! در دنیای برنامه‌نویسی هم همین قضیه وجود دارد. فرض کنیم کاربر به یک سری اطلاعات نیاز دارد که کلاس A وظیفه در اختیار گذاشتن این داده رو به کاربر بر عهده دارد. در کلاس A دو متد m1 و m2 وجود دارد. وظیفه متد m1 تولید داده است و وظیفه متد m2 بازگرداندن داده تولیدشده توسط متد m1 است. برای کاربر ما مهم این است که داده در اختیارش قرار بگیرد. پس اینکه به متد m1 دسترسی داشته باشد بی‌معنی است. یکی از راه‌های بسته‌بندی سازی یا Encapsulation در زبان‌های برنامه‌نویسی استفاده از Access Specifire ها (عمومی و خصوصی و...) هست. سطح‌های مختلفی برای بسته‌بندی یا Encapsulation وجود دارد. می‌توان دسترسی به یک کلاس را مدیریت کرد یا دسترسی به متدهای یک کلاس را مدیریت کرد و یا Property ها و فیلدهای یک کلاس رو مدیریت کرد.

حالا به بحث خودمان یعنی الگوی طراحی Command برمی‌گردیم. ما با استفاده از این الگوی طراحی فراخوانی یا call کردن یک متد را Encapsulate می‌کنیم و با استفاده از این کپسوله کردن ویژگی‌های زیادی را در اختیار ما می‌گذارد ازجمله می‌توانیم آن را ذخیره کنیم و دوباره فراوانی کنیم و یا امکان redo یا undo برای call کردن یک متد ایجاد کنیم.

#### مثال در دنیای واقعی

الگوی Command اجازه می‌دهد تا درخواست‌ها به‌عنوان اشیاء محصور شوند و از این طریق به مشتری اجازه می‌دهد تا با درخواست‌های مختلف پارامتر داده شود. "برگه سفارش خوراک" در یک رستوران نمونه‌ای از الگوی Command است. پیشخدمت از مشتری سفارش یا دستور می‌گیرد و با نوشتن آن در برگه سفارش خوراک، آن سفارش را محصور می‌کند. سفارش سپس برای یک آشپز در سفارش کوتاه صف می‌شود. توجه داشته باشید که پد "برگه¬های سفارش خوراک" استفاده‌شده توسط هر پیشخدمت به منو بستگی ندارد و بنابراین می‌توانند از دستورات مربوط به طبخ موارد مختلف استفاده کنند.

![](/files/-MH_V91o2OG_z-bbOYVc)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Encapsulate a request as an object, thereby letting you parameterize
clients with different requests, queue or log requests, and support
undoable operations.
"""
import abc

class Invoker:
    """       Ask the command to carry out the request.     """
    def __init__(self):
        self._commands = []

    def store_command(self, command):
        self._commands.append(command)

    def execute_commands(self):
        for command in self._commands:
            command.execute()

class Command(metaclass=abc.ABCMeta):
    """
    Declare an interface for executing an operation.
    """
    def __init__(self, receiver):
        self._receiver = receiver

    @abc.abstractmethod
    def execute(self):
        pass

class ConcreteCommand(Command):
    """
    Define a binding between a Receiver object and an action.
    Implement Execute by invoking the corresponding operation(s) on
    Receiver.
    """
    def execute(self):
        self._receiver.action()

class Receiver:
    """
    Know how to perform the operations associated with carrying out a
    request. Any class may serve as a Receiver.
    """
    def action(self):
        pass


def main():
    receiver = Receiver()
    concrete_command = ConcreteCommand(receiver)
    invoker = Invoker()
    invoker.store_command(concrete_command)
    invoker.execute_commands()

if __name__ == "__main__":
    main()

```

### Interpreter

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

#### مثال در دنیای واقعی

الگوی مترجم یک گرامر را برای یک‌زبان و یک مترجم برای تفسیر گرامر تعریف می‌کند. نوازندگان نمونه‌ای از مترجمان هستند. گام صدا و مدت‌زمان آن می‌تواند در نمادهای موسیقی روی دفتر نت نشان داده شود. این نمادها زبان موسیقی را فراهم می‌کند. نوازندگان موسیقی از این امتیاز استفاده می¬کنند و قادر به تکثیر صدای اصلی و مدت‌زمان هر صدا هستند.

![](/files/-MH_VPQ3C9jlS4N6Fkfv)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Define a represention for a grammar of the given language along with an
interpreter that uses the representation to interpret sentences in the
language.
"""
import abc

class AbstractExpression(metaclass=abc.ABCMeta):
    """
    Declare an abstract Interpret operation that is common to all nodes
    in the abstract syntax tree.
    """
    @abc.abstractmethod
    def interpret(self):
        pass

class NonterminalExpression(AbstractExpression):
    """
    Implement an Interpret operation for nonterminal symbols in the grammar.
    """
    def __init__(self, expression):
        self._expression = expression

    def interpret(self):
        self._expression.interpret()

class TerminalExpression(AbstractExpression):
    """
    Implement an Interpret operation associated with terminal symbols in
    the grammar.
    """
    def interpret(self):
        pass

def main():
    abstract_syntax_tree = NonterminalExpression(TerminalExpression())
    abstract_syntax_tree.interpret()

if __name__ == "__main__":
    main()


```

### Iterator

در همه زبان‌های برنامه‌نویسی داشتن مجموعه و فهرستی از اشیا (Collection) اتفاقی است که بسیار رخ می‌دهد. زمانی هم که ما یک مجموعه‌ای از اشیا داریم پیمایش این مجموعه برای دسترسی به اشیا یکی از مسائلی هست که ما با آن روبه‌رو می‌شویم. در اکثر زبان‌های برنامه‌نویسی تکنیک‌هایی برای پیمایش انواع Collection وجود دارد. (در زبان برنامه‌نویسی C# List و ArrayList دو نوع Collection می‌باشند)

فرض کنید ما یک Collection داریم که می‌خواهیم که آن را به‌وسیله یک حلقه for پیمایش کنیم. این پیمایش به‌صورت زیر می‌شود.

#### مثال در دنیای واقعی

Iterator روش‌هایی برای دستیابی به عناصر یک جسم به‌صورت متوالی و بدون افشای ساختار زیرین جسم ارائه می‌دهد. پرونده‌ها اشیاء کل هستند. در تنظیمات اداری که دسترسی به پرونده‌ها از طریق کارمندان اداری یا دبیرخانه انجام می‌شود، الگوی Iterator با منشی که به‌عنوان Iterator عمل می‌کند نشان داده می‌شود.

در تلویزیون‌های اولیه، از شماره‌گیری برای تغییر شبکه¬ها استفاده می‌شد. هنگام گشت‌وگذار در بین شبکه¬ها، بیننده ملزم به انتقال شماره‌گیری شبکه موردنظر، صرف‌نظر از این‌که آیا آن شبکه را دریافت کرده است یا خیر است. در تلویزیون‌های مدرن از دکمه بعدی و قبلی استفاده می‌شود. وقتی بیننده دکمه "بعدی" را انتخاب کند، شبکه تنظیم‌شده بعدی نمایش داده می‌شود. در نظر بگیرید در یک اتاق هتل در یک شهر عجیب تلویزیون را تماشا کنید. هنگام گشت‌وگذار از طریق شبکه¬های تلویزیونی، شماره شبکه اهمیتی ندارد، اما محتوای آن مهم است. اگر بیننده به محتوای آن شبکه علاقه¬ای نداشته باشد، بیننده می‌تواند بدون اطلاع از شماره آن، شبکه بعدی را درخواست کند.

![](/files/-MH_VgtAfkXC1sxYg4Z_)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Provide a way to access the elements of an aggregate objects equentially
without exposing its underlying representation.
"""
import collections.abc

class ConcreteAggregate(collections.abc.Iterable):
    """
    Implement the Iterator creation interface to return an instance of
    the proper ConcreteIterator.
    """
    def __init__(self):
        self._data = None

    def __iter__(self):
        return ConcreteIterator(self)

class ConcreteIterator(collections.abc.Iterator):
    """
    Implement the Iterator interface.
    """
    def __init__(self, concrete_aggregate):
        self._concrete_aggregate = concrete_aggregate

    def __next__(self):
        if True:  # if no_elements_to_traverse:
            raise StopIteration
        return None  # return element

def main():
    concrete_aggregate = ConcreteAggregate()
    for _ in concrete_aggregate:
        pass

if __name__ == "__main__":
    main()


```

### Mediator

الگوی طراحی Mediator همان‌طور که اسم از آن نیز می‌توان حدس زد وظیفه‌ی یک واسط و مدیریت کردن ارتباطات بین اشیا را بر عهده دارد. نقش‌های شرکت‌کننده در این الگوی طراحی موارد زیر هستند:

Mediator: یک اینترفیس است برای ارتباط بین اشیایی که باهم کار می‌کنند. ConcreteMediator: ارتباط بین اشیا در این کلاس تعریف می‌شود و همچنین اشیایی که قرار است باهم در ارتباط باشند را می‌شناسد. \
ColleagueClasses: همان اشیایی می‌باشند که باهم در ارتباط هستند و Mediator را می‌شناسند.

#### مثال در دنیای واقعی

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

![](/files/-MH_W6-VqeLPpLZQii94)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Define an object that encapsulates how a set of objects interact.
Mediator promotes loose coupling by keeping objects from referring to
each other explicitly, and it lets you vary their interaction
independently.
"""

class Mediator:
    """
    Implement cooperative behavior by coordinating Colleague objects.
    Know and maintains its colleagues.
    """
    def __init__(self):
        self._colleague_1 = Colleague1(self)
        self._colleague_2 = Colleague2(self)

class Colleague1:
    """
    Know its Mediator object.
    Communicate with its mediator whenever it would have otherwise
    communicated with another colleague.
    """
    def __init__(self, mediator):
        self._mediator = mediator

class Colleague2:
    """
    Know its Mediator object.
    Communicate with its mediator whenever it would have otherwise
    communicated with another colleague.
    """
    def __init__(self, mediator):
        self._mediator = mediator

def main():
    mediator = Mediator()

if __name__ == "__main__":
    main()

```

### Memento

کاربرد این الگوی طراحی زمانی است که ما نیاز داریم یک حالت خاص از یک شی‌ء را ذخیره کنیم تا در صورت نیاز شی‌ء را بعد از تغییر، به حالت ذخیره‌شده برگردانیم. همه ما کم‌وبیش درگیر بازی‌های کامپیوتری بوده‌ایم.Save کردن یک بازی دقیقاً حالتی است که می‌شود از الگوی طراحی Memento استفاده کرد. فقط نکته‌ای که در Memento باید موردتوجه قرار بگیرد این است که فقط همان Object ی که Memento را ایجاد کرده است می‌تواند به Memento خودش دسترسی داشته باشد.

نقش‌های شرکت‌کننده در این الگو موارد زیر هستند:

1. Memento: حالت شی‌ء را ذخیره می‌کند.Memento بر حساب نیاز می‌تواند همه یا قسمتی از حالت داخلی یک شی‌ء رو ذخیره کند. همچنین در برابر دسترسی‌های اشیاء غیر از شی‌ء اصلی محافظت می‌کند.
2. Originator: Memento شامل یک Snapshot از حالت فعلی را ایجاد می‌کند. همچنین از Memento برای Restore کردن استفاده می‌کند.
3. Caretaker: مسئول حفاظت و نگهداری از Memento است. همچنین هیچ عملیاتی رو محتوای Memento انجام نمی‌دهد.

#### مثال در دنیای واقعی

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

![](/files/-MH__GPmreA00Vz6GVOf)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Capture and externalize an object's internal state so that the object
can be restored to this state later, without violating encapsulation.
"""
import pickle

class Originator:
    """
    Create a memento containing a snapshot of its current internal
    state.
    Use the memento to restore its internal state.
    """
    def __init__(self):
        self._state = None

    def set_memento(self, memento):
        previous_state = pickle.loads(memento)
        vars(self).clear()
        vars(self).update(previous_state)

    def create_memento(self):
        return pickle.dumps(vars(self))

def main():
    originator = Originator()
    memento = originator.create_memento()
    originator._state = True
    originator.set_memento(memento)

if __name__ == "__main__":
    main()


```

### Observer

این الگو زمانی مور استفاده قرار می‌گیرد که ما چندین شی‌ء داریم (Observers) که به یک شی‌ء (Subject) وابسته هستند و زمانی که Subject ما تغییر حالت می‌دهد نیاز است شی‌ءهای Observer ما از این تغییر حالت آگاه شوند.\
&#x20;نقش‌های شرکت‌کننده در این الگو موارد زیر هستند:

1. Subject: Observers هایش را می‌شناسند. تعدادی Observer می‌توانند به یک Subject وابسته باشند. همچنین یک Interface جهت اضافه یا کم کردن Observer در اختیار قرار می‌دهد.
2. ConcreteSubject: حالت‌های مختلف یک Subject را در خود دارد. زمانی که تغییر حالت می‌دهد به Observer هایش اعلام می‌کند.
3. Observer: یک Updating Interface جهت دریافت Notification تغییرات Subject در اختیار قرار می‌دهد.
4. ConcreteObserver: یک Refrence به شی‌ء ConcreteSubject در خود دارد. حالتی را که باید توسط Subject ها پایدار بماند را در خود دارد. پیاده‌سازی می‌کند Updating Interface جهت دریافت حالت به‌روز شده Subject ها.

#### مثال در دنیای واقعی

Observer یک رابطه یک به چند را تعریف می‌کند به‌طوری‌که وقتی حالت یک شیء تغییر کند، به دیگران اطلاع داده می‌شود و به‌صورت خودکار بروز می‌شوند. برخی از حراج‌ها این الگوی را نشان می‌دهند. هر پیشنهاددهنده دارای یک تابلوی شماره‌گذاری شده است که برای نشان دادن پیشنهاد استفاده می‌شود. برگزارکننده مزایده را شروع می‌کند و هنگامی‌که یک تابلو برای قبول پیشنهاد بالا می¬رود، "مشاهده" می‌کند. پذیرش پیشنهاد قیمت، قیمت پیشنهادی را که به‌صورت پیشنهاد قیمت جدید برای همه داوطلبان پخش می‌شود، تغییر می‌دهد.

![](/files/-MH_lY_CHQf6wbkIIe6x)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Provide a way to access the elements of an aggregate objects equentially
without exposing its underlying representation.
"""
import collections.abc

class ConcreteAggregate(collections.abc.Iterable):
    """
    Implement the Iterator creation interface to return an instance of
    the proper ConcreteIterator.
    """
    def __init__(self):
        self._data = None

    def __iter__(self):
        return ConcreteIterator(self)

class ConcreteIterator(collections.abc.Iterator):
    """
    Implement the Iterator interface.
    """
    def __init__(self, concrete_aggregate):
        self._concrete_aggregate = concrete_aggregate

    def __next__(self):
        if True:  # if no_elements_to_traverse:
            raise StopIteration
        return None  # return element

def main():
    concrete_aggregate = ConcreteAggregate()
    for _ in concrete_aggregate:
        pass

if __name__ == "__main__":
    main()

```

### State

این Desgin Pattern این قابلیت رو به ما می‌دهد که ما بتوانیم بر اساس تغییر حالت داخلی یک شیء عملکردهای متفاوتی برای متدهای آن شیء داشته باشیم.

#### مثال در دنیای واقعی

الگوی State به یک شی‌ء اجازه می‌دهد تا هنگام تغییر وضعیت داخلی، رفتار خود را تغییر دهد. این الگوی را می‌توان در یک ماشین فروش مشاهده کرد. ماشین‌های واریز حالت‌هایی دارند که بر اساس موجودی، میزان ارز سپرده‌گذاری، امکان ایجاد تغییر، کالای انتخاب‌شده و غیره وجود دارد. وقتی پول واریز می‌شود و انتخابی صورت می‌گیرد، یک ماشین فروش کالا را تحویل می‌دهد و هیچ تغییری ندارد، محصول را تحویل می‌دهد و تغییر می‌کند، به دلیل کمبود پول در سپرده، کالایی را تحویل نمی¬دهد و یا به دلیل کاهش موجودی هیچ محصولی را تحویل نمی¬دهد.

![](/files/-MH_lqcJqodQ1jFZLlvF)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Allow an object to alter its behavior when its internal state changes.
The object will appear to change its class.
"""
import abc

class Context:
    """
    Define the interface of interest to clients.
    Maintain an instance of a ConcreteState subclass that defines the
    current state.
    """
    def __init__(self, state):
        self._state = state

    def request(self):
        self._state.handle()

class State(metaclass=abc.ABCMeta):
    """
    Define an interface for encapsulating the behavior associated with a
    particular state of the Context.
    """
    @abc.abstractmethod
    def handle(self):
        pass

class ConcreteStateA(State):
    """
    Implement a behavior associated with a state of the Context.
    """
    def handle(self):
        pass

class ConcreteStateB(State):
    """
    Implement a behavior associated with a state of the Context.
    """
    def handle(self):
        pass

def main():
    concrete_state_a = ConcreteStateA()
    context = Context(concrete_state_a)
    context.request()

if __name__ == "__main__":
    main()

```

### Strategy

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

#### مثال در دنیای واقعی

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

![](/files/-MH_mBNLTG2I6W83yCMt)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Define a family of algorithms, encapsulate each one, and make them
interchangeable. Strategy lets the algorithm vary independently from
clients that use it.
"""
import abc

class Context:
    """
    Define the interface of interest to clients.
    Maintain a reference to a Strategy object.
    """
    def __init__(self, strategy):
        self._strategy = strategy

    def context_interface(self):
        self._strategy.algorithm_interface()

class Strategy(metaclass=abc.ABCMeta):
    """
    Declare an interface common to all supported algorithms. Context
    uses this interface to call the algorithm defined by a
    ConcreteStrategy.
    """
    @abc.abstractmethod
    def algorithm_interface(self):
        pass

class ConcreteStrategyA(Strategy):
    """
    Implement the algorithm using the Strategy interface.
    """
    def algorithm_interface(self):
        pass

class ConcreteStrategyB(Strategy):
    """
    Implement the algorithm using the Strategy interface.
    """
    def algorithm_interface(self):
        pass

def main():
    concrete_strategy_a = ConcreteStrategyA()
    context = Context(concrete_strategy_a)
    context.context_interface()

if __name__ == "__main__":
    main()


```

### Template method

الگوی Template Method(متد قلابدار-متد قالب) در دسته الگوهای رفتاری قرار دارد.

اسکلت یک الگوریتم در یک عملیات را تعریف می‌کند، بعضی مراحل را به زیر کلاس‌ها منتقل می‌کند.Template Method اجازه می‌دهد که زیر کلاس‌ها گام‌های خاصی از یک الگوریتم را دوباره تغییر دهند بدون تغییر ساختار الگوریتم. به‌عبارت‌دیگر اسکلت کلی الگوریتم را تعریف کرده و این امکان را فراهم می‌کند که بدون تغییر ساختار کلی الگوریتم بتوان برخی از مراحل آن را به زیر کلاس‌ها سپرد.&#x20;

#### مثال در دنیای واقعی

&#x20;روش قالب یا اسکلت یک الگوریتم را در یک عمل تعریف می‌کند و برخی مراحل را به زیر کلاس‌ها واگذار می‌کند. سازندگان خانه هنگام تهیه زیرمجموعه جدید از روش الگو استفاده می‌کنند. یک زیرمجموعه معمولی شامل تعداد محدودی از برنامه‌های کف با انواع مختلف در دسترس برای هر یک است. در یک طرح طبقه، پایه، فریم، لوله‌کشی و سیم‌کشی برای هر خانه یکسان خواهد بود. تنوع در مراحل بعدی ساخت معرفی‌شده است تا انواع گسترده‌تری از مدل‌ها را تولید کند.

مثال دیگر: کارهای روزمره یک کارگر

![](/files/-MH_mWZ65vzyaK96JYmz)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Define the skeleton of an algorithm in an operation, deferring some
steps to subclasses. Template Method lets subclasses redefine certain
steps of an algorithm without changing the algorithm's structure.
"""
import abc

class AbstractClass(metaclass=abc.ABCMeta):
    """
    Define abstract primitive operations that concrete subclasses define
    to implement steps of an algorithm.
    Implement a template method defining the skeleton of an algorithm.
    The template method calls primitive operations as well as operations
    defined in AbstractClass or those of other objects.
    """
    def template_method(self):
        self._primitive_operation_1()
        self._primitive_operation_2()

    @abc.abstractmethod
    def _primitive_operation_1(self):
        pass

    @abc.abstractmethod
    def _primitive_operation_2(self):
        pass

class ConcreteClass(AbstractClass):
    """
    Implement the primitive operations to carry out
    subclass-specificsteps of the algorithm.
    """
    def _primitive_operation_1(self):
        pass

    def _primitive_operation_2(self):
        pass

def main():
    concrete_class = ConcreteClass()
    concrete_class.template_method()

if __name__ == "__main__":
    main()


```

### Visitor

اگر بخواهیم به کلاسی بدون اینکه به ساختار آن دست بزنیم متدهایی را اضافه کنیم از این الگو استفاده می‌کنیم. این الگو تلاش می‌کند تا بین لایه Business logic (برای آشنایی با مفهوم Business Logic و برنامه‌نویسی سه لایه به مقاله معماری سه لایه در ASP.NET مراجعه کنید) و الگوریتم جدایی ایجاد کند. ما می‌توانیم منطق جدیدی به برنامه اضافه کنیم بدون اینکه به ساختار دیتای خود دست بزنیم.&#x20;

#### مثال در دنیای واقعی

&#x20;الگوی Visitor عملیاتی است که باید روی عناصر ساختار یک شی‌ء انجام شود بدون اینکه کلاس¬هایی را که در آن کار می‌کند تغییر دهید. این الگو را می‌توان در عملکرد یک شرکت تاکسی مشاهده کرد. وقتی شخصی با یک شرکت تاکسی (پذیرش بازدیدکننده) تماس می‌گیرد، این شرکت یک ماشین را برای مشتری اعزام می‌کند. پس از ورود به تاکسی، مشتری یا ویزیتور دیگر کنترل حمل‌ونقل خود را ندارد و کنترل حمل‌ونقل با تاکسی (راننده) است.

![](/files/-MH_mnPTMe830JYgqLQm)

حالا به سراغ پیاده سازی این الگو میرویم. به مثال زیر دقت کنید.

```python
"""
Represent an operation to be performed on the elements of an object
structure. Visitor lets you define a new operation without changing the
classes of the elements on which it operates.
"""
import abc

class Element(metaclass=abc.ABCMeta):
    """
    Define an Accept operation that takes a visitor as an argument.
    """
    @abc.abstractmethod
    def accept(self, visitor):
        pass

class ConcreteElementA(Element):
    """
    Implement an Accept operation that takes a visitor as an argument.
    """
    def accept(self, visitor):
        visitor.visit_concrete_element_a(self)

class ConcreteElementB(Element):
    """
    Implement an Accept operation that takes a visitor as an argument.
    """
    def accept(self, visitor):
        visitor.visit_concrete_element_b(self)

class Visitor(metaclass=abc.ABCMeta):
    """
    Declare a Visit operation for each class of ConcreteElement in the
    object structure. The operation's name and signature identifies the
    class that sends the Visit request to the visitor. That lets the
    visitor determine the concrete class of the element being visited.
    Then the visitor can access the element directly through its
    particular interface.
    """
    @abc.abstractmethod
    def visit_concrete_element_a(self, concrete_element_a):
        pass

    @abc.abstractmethod
    def visit_concrete_element_b(self, concrete_element_b):
        pass
class ConcreteVisitor1(Visitor):
    """
    Implement each operation declared by Visitor. Each operation
    implements a fragment of the algorithm defined for the corresponding
    class of object in the structure. ConcreteVisitor provides the
    context for the algorithm and stores its local state. This state
    often accumulates results during the traversal of the structure.
    """
    def visit_concrete_element_a(self, concrete_element_a):
        pass

    def visit_concrete_element_b(self, concrete_element_b):
        pass

class ConcreteVisitor2(Visitor):
    """
    Implement each operation declared by Visitor. Each operation
    implements a fragment of the algorithm defined for the corresponding
    class of object in the structure. ConcreteVisitor provides the
    context for the algorithm and stores its local state. This state
    often accumulates results during the traversal of the structure.
    """
    def visit_concrete_element_a(self, concrete_element_a):
        pass

    def visit_concrete_element_b(self, concrete_element_b):
        pass

def main():
    concrete_visitor_1 = ConcreteVisitor1()
    concrete_element_a = ConcreteElementA()
    concrete_element_a.accept(concrete_visitor_1)

if __name__ == "__main__":
    main()

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://iarash.gitbook.io/payton-based-on-documentation/fsl-hftm/algwhay-trahy-dr-paytwn.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
