Design Mode | Prototype Mode

1 | Overview of Prototype Mode

Prototype mode is a special creation mode, which obtains more identical or similar objects by copying an existing object. The prototype mode can improve the efficiency of creating objects of the same type in the system and simplify the creation process. 

In "Journey to the West", the story of "Sun Wukong plucking hair and turning monkey" is almost known to everyone. Monkey hair used monkey hair to copy many "avatars" that are exactly the same as his own. This kind of scene is called the prototype mode in the field of object-oriented software design, and Monkey King is called the prototype object.

Definition of prototype pattern

  • Prototype mode: Use a prototype instance to specify the type of object to be created, and create a new object by copying this prototype.
  • Prototype Pattern:Specify the kinds of objects to create using a protptypical instance, and create new objects by copying this protptype.

How the prototype mode works

  • Pass a prototype object to the object to be created (that is, the client object), and the object to be created realizes the process of creating a new object by requesting the prototype object to copy itself. This process of creating new objects is also called "cloning objects". The factory for creating new objects is the prototype class itself, and the factory method is implemented by the clone method responsible for copying the prototype object.

Note: Objects created by cloning objects are brand new objects, and they have new addresses in memory. Usually, the new object produced by the clone will not have any effect on the prototype object, and each cloned object is independent of each other. After modifying the cloned object, a series of similar but incomplete objects can be obtained.

2 | The structure and realization of the prototype pattern

2.1 The structure of the prototype model

The prototype mode contains the following 3 roles:

  • (1) Prototype (abstract prototype class) : It is the interface that declares the clone method, and is the common parent class of all concrete prototype classes. It can be an abstract class or an interface, or even a concrete implementation class.
  • (2) ConcretePrototvpe (concrete prototype class) : It implements the clone method declared in the abstract prototype class, and returns a cloned object of its own in the clone method.
  • (3) Client (Customer White Class) : In the client class, let a prototype object clone itself to create a new object. You only need to directly instantiate or create a prototype object through factory methods, and then call the object's The clone method can be used to obtain multiple identical pairs. The Prntotvne version of the fish pumping company is programmed by the Ganjia Baimi Company. Therefore, the user can select the specific original rice according to the needs. It is very convenient to push a few off prototype classes.

2.2 Shallow clone and deep clone of prototype mode

According to whether to copy the member variables of the reference type contained in the prototype object while copying the prototype object, the cloning mechanism of the prototype mode is divided into two types: Shallow Clone and Deep Clone, sometimes called shallow copy And deep copy.

(1) Shallow Clone

In shallow cloning, if the members of the prototype object are also value class punishments (such as int, double, byte, bool, char and other basic data types), a copy will be copied to the subdued object. If the member variable of the prototype object is a reference type (Such as complex data types such as classes, interfaces, arrays, etc.), the address of the referenced object is copied to the overridden object, that is, the member variables of the prototype object and the cloned object point to the same memory address. Simply put, in shallow cloning, when the prototype object is copied, only the member variables of itself and the value type contained in it are copied, while the member variables of the reference type are not copied.

(2) Deep Clone

In deep cloning, regardless of whether the member variable of the prototype object is a value type or a reference type, it will be copied to the cloned object, and deep cloning will also copy all reference objects of the prototype object to the cloned object. Simply put, in deep cloning, in addition to the object itself is copied, all the member variables contained in the object will also be copied.

2.2 Implementation of the prototype mode

The key to implementing the prototype mode is how to implement the cloning method. There are two commonly used methods of cloning in C#:

2.2.1 General cloning implementation method , the sample code is as follows:

abstract class Prototype 
{
    public abstract Prototype Clone();
}

class ConcretePrototype : Prototype
{
    /// <summary>
    /// 成员变量
    /// </summary>
    public string Attr { get; set; }

    /// <summary>
    /// 克隆方法,通过赋值的方式来实现对象的复制。
    /// </summary>
    /// <returns></returns>
    public override Prototype Clone() => new ConcretePrototype
    {
        Attr = Attr //成员变量赋值
    };
}

 Client calling sample code:

// 1.创建 ConcretePrototype 对象作为原型。
ConcretePrototype prototype = new ConcretePrototype();
// 2. 原型实例对象 prototype 调用克隆方法 Clone() 创建克隆对象。
ConcretePrototype copy = (ConcretePrototype)prototype.Clone();

 Note: This method is a general method of the prototype mode and has nothing to do with the characteristics of the programming language itself. In addition to C#, other object-oriented programming languages ​​can also use this form to practice the cloning of prototype objects. In the above cloning method Clone(), if the replication is achieved by creating a brand new member object, it is a deep cloning implementation scheme. The string/String object in C# language has particularity. As long as the two strings are the same internally, whether it is value assignment or creation of a new object, they will always have only one copy in memory. For more information, please refer to " C# String Residency Mechanism ".

Reference: [String immutability and residency mechanism] https://www.cnblogs.com/SignX/p/10933482.html

2.2.2 MemberwiseClone() method and ICloneable interface in C#

In the C# language, a MemberwiseClone() method is provided to implement shallow cloning. This method is very convenient to use, and the MemberwiseClone() method of an existing object can be called in between to implement object cloning. The sample code is as follows:

class Member { }

class ConcretePrototypeA 
{
    /// <summary>
    /// 成员变量
    /// </summary>
    public Member MyMember { get; set; }

    /// <summary>
    /// 克隆方法,通过赋值的方式来实现对象的复制。
    /// </summary>
    /// <returns></returns>
    public ConcretePrototypeA Clone() => (ConcretePrototypeA)this.MemberwiseClone(); //浅克隆      
}

 The client is called, and the test output confirms that the cloning method is shallow cloning.

 The ICloneable interface acts as an abstract prototype class, and the concrete prototype class is usually a subclass that implements the interface. The sample code is as follows:

class ConcretePrototypeB: System.ICloneable
{
    /// <summary>
    /// 成员变量
    /// </summary>
    public Member MyMember { get; set; }

    /// <summary>
    /// 实现深克隆
    /// </summary>
    /// <returns></returns>
    public object Clone()
    {
        ConcretePrototypeB copy = this.MemberwiseClone() as ConcretePrototypeB; //对象转换
        Member newMember = new Member();
        copy.MyMember = newMember;
        return copy;
    }
}

Called by the client, and the test output confirms that the cloning method is a deep cloning.

3 | Prototype Manager

The prototype manager (Prototype Manager) stores multiple prototype objects in a collection for client use. It is a factory responsible for cloning objects. A collection is defined to store prototype objects. If you need a prototype object A clone can be obtained by copying the corresponding prototype object in the collection. Program the abstract class in the prototype manager for easy extension. The structure is as follows:

 PrototypeManager PrototypeManager code implementation:

using System.Collections;

namespace PrototypePattern
{
    /// <summary>
    /// 原型管理器-PrototypeManager
    /// </summary>
    class PrototypeManager
    {
        #region SingleProfit 单例模式
        //创建私有化静态obj锁
        private static readonly object _ObjLock = new object();
        //创建私有静态字段,接收类的实例化对象
        private static volatile PrototypeManager _SingleProfit = null; //volatile 促进线程安全,保证线程有序执行 
        //构造函数私有化
        private PrototypeManager() { }
        //创建单利对象资源并返回
        public static PrototypeManager CreateSingleProfitObj()
        {
            if (_SingleProfit == null)
            {
                lock (_ObjLock)
                {
                    if (_SingleProfit == null)
                    {
                        _SingleProfit = new PrototypeManager();
                    }
                }
            }
            return _SingleProfit;
        } 
        #endregion

        /// <summary>
        /// Hashtable 存储原型对象
        /// </summary>
        private readonly static Hashtable hashTable = new Hashtable();

        /// <summary>
        /// Hashtable 新增原型对象
        /// </summary>
        /// <param name="key"></param>
        /// <param name="prototype"></param>
        public void Add(string key, Prototype prototype) 
        {
            hashTable.Add(key,prototype);
        }

        /// <summary>
        /// 获取克隆对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public Prototype Get(string key) 
        {
            Prototype copy = ((Prototype)hashTable[key]).Clone(); //通过(内置)克隆方法创建新对象
            return copy;
        }
    }
}

In actual development, the PrototypeManager class is usually designed as a singleton class (singleton mode) to ensure that there is one and only one PrototypeManager object in the system, which is not only conducive to saving system resources, but also can better control the prototype manager object . Add two classes, ConcretePrototypeC and ConcretePrototypeD

#region 配合 PrototypeManager 使用
class ConcretePrototypeC : Prototype
{
    public override Prototype Clone()
    {
        return (ConcretePrototypeC) this.MemberwiseClone();
    }
}

class ConcretePrototypeD : Prototype
{
    public override Prototype Clone()
    {
        return (ConcretePrototypeD) this.MemberwiseClone();
    }
}
#endregion

Client calling method

4 | Pros and cons of prototype mode and applicable environment

As a way to quickly create a large number of identical or similar objects, the prototype mode is widely used in software development. The copy (Ctrl+C) and paste (Ctrl+V) operations provided by many software are typical applications of the prototype mode.

4.1 The main advantages of the prototype mode

  • (1) When the object instance to be created is more complex, using the prototype mode can simplify the creation process of the object, and by making an existing instance, the efficiency of creating a new instance can be improved.
  • (2) The scalability is better. Because the abstract prototype class is provided in the prototype mode, the client can program the abstract prototype, and the specific prototype class is written in the configuration file. Adding or reducing product classes has no effect on the original system. Any impact.
  • (3) The prototype model provides a simplified creation structure. The factory method model often needs to have a factory hierarchy structure that is the same as the product class hierarchy, while the prototype model does not need to be like this. The product copy in the prototype model is encapsulated in the type class. The clone method in the implementation does not require a special factory class to create products.
  • (4) You can save the state of the object by deep cloning, and use the prototype mode to copy the object and save its state for use when needed (for example, to restore to a certain historical state), which can assist in the undo operation .

4.2 The main disadvantages of the prototype model

  • (1) It is necessary to equip each class with a cloning method, and the cloning method is located inside a class. When the existing class is modified, the source code needs to be modified, which violates the principle of opening and closing .
  • (2) It is necessary to write more complex codes when implementing deep cloning, and when there are multiple nested references between objects, in order to achieve deep cloning, the classes corresponding to each layer of objects must support deep cloning, which may be difficult to achieve. kind of hard.

4.3 Applicable environment of prototype mode

  • (1) The cost of creating a new object is relatively high (for example, initialization takes a long time and takes up too much CPU resources or network resources). The new object can be obtained by copying the existing object. If it is a similar object, you can use it The member variables are slightly modified.
  • (2) The system needs to save the state of the object, and the state of the object changes very little.
  • (3) It is necessary to avoid the use of hierarchical factory classes to create hierarchical objects, and the instance object of the class has only one or a few combined states. The new instance obtained by copying the prototype object may be better than using the constructor to create a new instance More convenient.

Guess you like

Origin blog.csdn.net/ChaITSimpleLove/article/details/114805218