デザインモード|プロトタイプモード

1 |プロトタイプモードの概要

プロトタイプモードは特別な作成モードであり、既存のオブジェクトをコピーすることで、より同一または類似のオブジェクトを取得します。プロトタイプモードでは、システム内で同じタイプのオブジェクトを作成する効率を向上させ、作成プロセスを簡素化できます。 

「西への旅」では、「孫悟空が髪を抜いて猿を回す」という話はほとんどの人に知られています。猿の髪は猿の髪を使って、自分とまったく同じ多くの「アバター」をコピーしました。このようなシーンは、オブジェクト指向ソフトウェア設計の分野ではプロトタイプモードと呼ばれ、孫悟空はプロトタイプオブジェクトと呼ばれます。

プロトタイプパターンの定義

  • プロトタイプモード:プロトタイプインスタンスを使用して、作成するオブジェクトのタイプを指定し、このプロトタイプをコピーして新しいオブジェクトを作成します。
  • プロトタイプパターン:プロトタイプインスタンスを使用して作成するオブジェクトの種類を指定し、このプロトタイプをコピーして新しいオブジェクトを作成します。

プロトタイプモードのしくみ

  • プロトタイプオブジェクトを作成するオブジェクト(つまり、クライアントオブジェクト)に渡すと、作成するオブジェクトは、プロトタイプオブジェクトにそれ自体をコピーするように要求することにより、新しいオブジェクトを作成するプロセスを実現します。この新しいオブジェクトの作成プロセスは「クローンオブジェクト」とも呼ばれます。新しいオブジェクトを作成するためのファクトリはプロトタイプクラス自体であり、ファクトリメソッドはプロトタイプオブジェクトのコピーを担当するクローンメソッドによって実装されます。

注:オブジェクトのクローンを作成して作成されたオブジェクトはまったく新しいオブジェクトであり、メモリ内に新しいアドレスがあります。通常、クローンによって生成された新しいオブジェクトはプロトタイプオブジェクトに影響を与えず、クローンされた各オブジェクトは互いに独立しています。複製されたオブジェクトを変更した後、一連の類似しているが不完全なオブジェクトを取得できます。

2 |プロトタイプパターンの構造と実現

2.1プロトタイプモデルの構造

プロトタイプモードには、次の3つの役割が含まれます。

  • (1)プロトタイプ(抽象プロトタイプクラス):クローンメソッドを宣言するインターフェースであり、すべての具象プロトタイプクラスに共通の親クラスであり、抽象クラスやインターフェース、さらには具象実装クラスでもかまいません。
  • (2)ConcretePrototvpe(concreteプロトタイプクラス):抽象プロトタイプクラスで宣言されたcloneメソッドを実装し、cloneメソッドで独自のcloneオブジェクトを返します。
  • (3)クライアント(カスタマーホワイトクラス):クライアントクラスで、プロトタイプオブジェクトのクローンを作成して新しいオブジェクトを作成します。ファクトリメソッドを使用してプロトタイプオブジェクトを直接インスタンス化または作成してから、オブジェクトの複数の同一のペアを呼び出すだけです。 PrntotvneはGanjiaBaimi Companyによってプログラムされているため、ユーザーはニーズに応じて特定のオリジナルの米を選択できます。プロトタイプクラスをいくつかプッシュするのは非常に便利です。

2.2プロトタイプモードの浅いクローンと深いクローン

プロトタイプオブジェクトのコピー中に、プロトタイプオブジェクトに含まれる参照型のメンバー変数をコピーするかどうかによって、プロトタイプモードのクローン作成メカニズムは、浅いクローン深いクローンの2つのタイプに分けられ浅いコピーと深いコピーと呼ばれることもあります。

(1)浅いクローン

浅いクローニングでは、プロトタイプオブジェクトのメンバーが値クラスの罰(int、double、byte、bool、char、その他の基本的なデータ型など)でもある場合、コピーは抑制されたオブジェクトにコピーされます。プロトタイプオブジェクトは参照型(クラス、インターフェイス、配列などの複雑なデータ型など)であり、参照されたオブジェクトのアドレスは、オーバーライドされたオブジェクト、つまり、プロトタイプオブジェクトのメンバー変数とクローン化されたオブジェクトは同じメモリアドレスを指します。簡単に言えば、浅いクローン作成では、プロトタイプオブジェクトがコピーされると、それ自体のメンバー変数とそれに含まれる値型のみがコピーされ、参照型のメンバー変数はコピーされません。

(2)ディープクローン

ディープクローンでは、プロトタイプオブジェクトのメンバー変数が値型であるか参照型であるかに関係なく、クローンオブジェクトにコピーされます。また、ディープクローンでは、プロトタイプオブジェクトのすべての参照オブジェクトもクローンオブジェクトにコピーされます。簡単に言えば、ディープクローンでは、オブジェクト自体がコピーされるだけでなく、オブジェクトに含まれるすべてのメンバー変数もコピーされます。

2.2プロトタイプモードの実装

プロトタイプモードを実装するための鍵は、クローン作成方法を実装する方法です。C#で一般的に使用されるクローン作成方法は2つあります。

2.2.1一般的なクローン作成の実装方法。サンプルコードは次のとおりです。

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 //成员变量赋值
    };
}

 クライアント呼び出しサンプルコード:

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

 注:このメソッドはプロトタイプモードの一般的なメソッドであり、プログラミング言語自体の特性とは関係ありません.C#に加えて、他のオブジェクト指向プログラミング言語もこのフォームを使用してプロトタイプのクローニングを練習できますオブジェクト。上記のクローン作成メソッドClone()で、新しいメンバーオブジェクトを作成することによってレプリケーションが実現される場合、それはディープクローン作成の実装スキームです。C#言語の文字列/文字列オブジェクトは特殊性があります.2つの文字列が内部的に同じである限り、値の割り当てであろうと新しいオブジェクトの作成であろうと、メモリには常に1つのコピーしかありません。詳細については、「C#文字列常駐メカニズムを参照してください

参照:[文字列の不変性と常駐メカニズム] https://www.cnblogs.com/SignX/p/10933482.html

2.2.2 C#のMemberwiseClone()メソッドとICloneableインターフェイス

C#言語では、浅いクローンを実装するためにMemberwiseClone()メソッドが提供されています。このメソッドは非常に使いやすく、既存のオブジェクトのMemberwiseClone()メソッドを間に呼び出してオブジェクトのクローンを実装できます。サンプルコードは次のとおりです。

class Member { }

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

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

 クライアントが呼び出され、テスト出力により、クローン作成方法が浅いクローン作成であることが確認されます。

 ICloneableインターフェイスは、抽象プロトタイプクラスとして機能し、具象プロトタイプクラスは通常、インターフェイスを実装するサブクラスです。サンプルコードは次のとおりです。

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;
    }
}

クライアントによって呼び出され、テスト出力により、クローン作成方法がディープクローン作成であることが確認されます。

3 |プロトタイプマネージャー

プロトタイプマネージャー(Prototype Manager)は、クライアントが使用するコレクションに複数のプロトタイプオブジェクトを格納します。オブジェクトのクローン作成を担当するファクトリです。コレクションは、プロトタイプオブジェクトを格納するために定義されます。プロトタイプオブジェクトが必要な場合クローンは、コピーすることで取得できます。コレクション内の対応するプロトタイプオブジェクト。拡張を容易にするために、プロトタイプマネージャーで抽象クラスをプログラムします。構造は次のとおりです。

 PrototypeManager PrototypeManagerコードの実装:

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;
        }
    }
}

実際の開発では、PrototypeManagerクラスは通常シングルトンクラス(シングルトンモード)として設計され、システム内にPrototypeManagerオブジェクトが1つだけ存在するようにします。これにより、システムリソースを節約できるだけでなく、プロトタイプをより適切に制御できます。マネージャーオブジェクト。ConcretePrototypeCとConcretePrototypeDの2つのクラスを追加します

#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

クライアント呼び出しメソッド

4 |プロトタイプモードと適用可能な環境の長所と短所

多数の同一または類似のオブジェクトをすばやく作成する方法として、プロトタイプモードはソフトウェア開発で広く使用されています。多くのソフトウェアで提供されるコピー(Ctrl + C)および貼り付け(Ctrl + V)操作は、プロトタイプの典型的なアプリケーションです。モード。

4.1プロトタイプモードの主な利点

  • (1)作成するオブジェクトインスタンスがより複雑な場合、プロトタイプモードを使用すると、オブジェクト作成のプロセスを簡素化でき、既存のインスタンスを作成すると、新しいインスタンスの作成効率を向上させることができます。
  • (2)スケーラビリティが向上します。抽象プロトタイプクラスはプロトタイプモードで提供されるため、クライアントは抽象プロトタイプをプログラムでき、特定のプロトタイプクラスが構成ファイルに書き込まれます。製品クラスを追加または削減しても、元のシステム。影響。
  • (3)プロトタイプモデルは、簡略化された作成構造を提供します。ファクトリメソッドモデルは、多くの場合、製品クラス階層と同じファクトリ階層構造を持つ必要がありますが、プロトタイプモデルはこのようなものである必要はありません。プロトタイプモデルはtypeクラスにカプセル化されます。実装のcloneメソッドは、製品を作成するために特別なファクトリクラスを必要としません。
  • (4)ディープクローニングによってオブジェクトの状態を保存し、プロトタイプモードを使用してオブジェクトをコピーし、必要に応じて使用するためにその状態を保存できます(たとえば、特定の履歴状態に復元するため)。操作を元に戻します。

4.2プロトタイプモデルの主な欠点

  • (1)各クラスにクローンメソッドを装備する必要があり、クローンメソッドはクラス内にあります。既存のクラスを変更する場合は、ソースコードを変更する必要があり、開閉の原則に違反します。
  • (2)ディープクローニングを実装する場合は、より複雑なコードを記述する必要があり、オブジェクト間に複数のネストされた参照がある場合、ディープクローニングを実現するには、オブジェクトの各レイヤーに対応するクラスがディープクローニングをサポートする必要があります。これは難しい場合があります。達成するために。ちょっと難しい。

4.3プロトタイプモードの適用環境

  • (1)新しいオブジェクトの作成コストが比較的高い(たとえば、初期化に時間がかかり、CPUリソースやネットワークリソースを大量に消費する)。新しいオブジェクトは、既存のオブジェクトをコピーすることで取得できます。同様のオブジェクト、あなたはそれを使うことができますメンバー変数はわずかに変更されています。
  • (2)システムはオブジェクトの状態を保存する必要があり、オブジェクトの状態はほとんど変化しません。
  • (3)階層オブジェクトを作成するために階層ファクトリクラスの使用を避ける必要があり、クラスのインスタンスオブジェクトには1つまたは少数の結合状態しかありません。プロトタイプオブジェクトをコピーして取得した新しいインスタンスは、を使用するよりも優れている場合があります。新しいインスタンスを作成するためのコンストラクターより便利です。

おすすめ

転載: blog.csdn.net/ChaITSimpleLove/article/details/114805218