🎉 Ура! После трёх лет работы, я наконец выпустил английскую версию книги о паттернах! Вот она »

C#: Прототип

Prototype Прототип Prototype

Прототип — это порождающий паттерн, который позволяет копировать объекты любой сложности без привязки к их конкретным классам.

Все классы—Прототипы имеют общий интерфейс. Поэтому вы можете копировать объекты, не обращая внимания на их конкретные типы и всегда быть уверены, что получите точную копию. Клонирование совершается самим объектом-прототипам, что позволяет ему скопировать значения всех полей, даже приватных.

Подробней о Прототипе

Особенности паттерна на C#

Сложность:

Популярность:

Применимость: Паттерн Прототип реализован в базовой библиотеке C# посредством интерфейса Cloneable.

Признаки применения паттерна: Прототип легко определяется в коде по наличию методов clone, copy и прочих.

Пример: Структура паттерна

Этот пример показывает структуру паттерна Прототип, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.

Program.cs: Пример структуры паттерна

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RefactoringGuru.DesignPatterns.Prototype.Structural
{
    class Program
    {
        static void Main(string[] args)
        {
            Client client = new Client();
            client.ClientCode();
        }
    }

    class Client
    {
        public void ClientCode()
        {
            Prototype prototype = new Prototype();
            prototype.Primitive = 245;
            prototype.Component = new DateTime();
            prototype.CircularReference = new ComponentWithBackReference(prototype);

            Prototype clone = prototype.Clone();

            if(prototype.Primitive == clone.Primitive)
            {
                Console.Write("Primitive field values have been carried over to a clone. Yay!\n");
            }
            else
            {
                Console.Write("Primitive field values have not been copied. Booo!\n");
            }

            if (prototype.Component != clone.Component)
            {
                Console.Write("Simple component has been cloned. Yay!\n");
            }
            else
            {
                Console.Write("Simple component has not been cloned. Booo!\n");
            }

            if (prototype.CircularReference != clone.CircularReference)
            {
                Console.Write("Component with back reference has been cloned. Yay!\n");
            }
            else
            {
                Console.Write("Component with back reference has not been cloned. Booo!\n");
            }

            if (clone.CircularReference.Prototype != prototype)
            {
                Console.Write("Component with back reference is not linked to original object. Yay!\n");
            }
            else
            {
                Console.Write("Component with back reference is linked to original object. Booo!\n");
            }
        }
    }

    public class Prototype
    {
        public int Primitive { get; set; }

        public DateTime Component { get; set; }

        public ComponentWithBackReference CircularReference { get; set; }

        public Prototype()
        { }
        
        public Prototype Clone()
        {
            Prototype clone = this.MemberwiseClone() as Prototype;

            clone.Component = this.Component.MemberwiseClone() as DateTime;

            clone.CircularReference = this.CircularReference.MemberwiseClone() as ComponentWithBackReference;
            clone.CircularReference.Prototype = this;

            return clone;
        }
    }

    public class ComponentWithBackReference
    {
        public Prototype Prototype { get; set; }

        public ComponentWithBackReference(Prototype p)
        {
            Prototype = p;
        }
    }
}

Output.txt: Результат выполнения

Primitive field values have been carried over to a clone. Yay!
Simple component has been cloned. Yay!
Component with back reference has been cloned. Yay!
Component with back reference is linked to the clone. Yay!