デザインパターン|ファクトリ(メソッド)パターン

1 |ファクトリ(メソッド)モードの概要

問題を考えると、単純なファクトリパターンを使用して設計されたボタンファクトリクラスは、長方形のボタン、丸いボタン、ひし形のボタンなど、特定のタイプのボタンインスタンスを返すことができます。楕円形のボタンなどのシステムでは、特定の製品カテゴリを追加する必要があります。また、ファクトリコードを変更する必要があります。これにより、デザイン全体が開閉の原則にある程度違反します。

変更計画では、すべての製品の作成を担当するボタンファクトリクラスが提供されなくなりました。代わりに、特定の製品の作成プロセスが特別なファクトリサブクラスに渡されて完了します。

この抽象化の結果、この構造は特定のファクトリクラスを変更せずに新製品を導入できます。新しいボタンタイプが表示された場合は、この新しいタイプのボタンに特定のファクトリクラスを定義するだけです。この新しいボタンのインスタンスを作成します。これにより改善されました。デザインスキームはファクトリメソッドパターンです。

ファクトリメソッドパターンは、抽象ファクトリクラスを導入します。これにより、単純なファクトリパターンよりも優れており、システムが開閉の原則に沿ったものになります。

1.1ファクトリ(メソッド)パターンの定義:

  • ファクトリ(メソッド)パターン:オブジェクトを作成するためのインターフェイスを定義しますが、インスタンス化するクラスをサブクラスに決定させます。ファクトリメソッドパターンは、クラスのサブクラス(派生クラス)へのインスタンス化を遅らせます。
  • ファクトリメソッドパターン:オブジェクトを作成するためのインターフェイスを定義しますが、インスタンス化するクラスをサブクラスに決定させます。ファクトリメソッドを使用すると、クラスはインスタンス化をサブクラスに延期できます。

2 | ファクトリ(メソッド)パターンの構造と実現

2.1ファクトリ(メソッド)パターンの構造

ファクトリパターンは、抽象ファクトリメソッドを宣言するための抽象ファクトリインターフェイスを提供し、そのサブクラスによって実装されるファクトリメソッドは、具体的な製品オブジェクトを作成します。

interface Factory
{
    Product FactoryMethod();
}

 ファクトリメソッドは抽象ファクトリで宣言されていますが、ファクトリメソッドは実装されていません。具体的な製品オブジェクトの作成はそのサブクラスを担当します。クライアントは実行時に抽象ファクトリプログラミング用の具体的なファクトリクラスを指定でき、具体的なファクトリはクラスはファクトリメソッドを実装します。特定のファクトリが異なれば、特定の製品も異なります。一般的なコードは次のとおりです。

class ConcreteFactory : Factory
{
    public Produet FacoryMethd()
    {
       return new ConcreteProduet(); 
    }
}

2.2ファクトリ(メソッド)パターンの実現

単純なファクトリパターンと比較して、ファクトリメソッドパターンの最も重要な機能は、インターフェイス、抽象クラス、または具象クラスの抽象ファクトリロールの導入です。

上の図からわかるように、ファクトリメソッドパターンには次の4つの役割が含まれています。

  • (1)Product(abstract product)製品を定義するインターフェースであり、ファクトリメソッドパターンによって作成されたオブジェクトのスーパータイプ、つまり製品オブジェクトの共通の親クラスです。
  • (2)コンクリート製品(コンクリート製品):抽象的な製品インターフェースを実現し、特定の種類のコンクリート製品を特殊なコンクリート工場で作成し、コンクリート工場とコンクリート製品を1対1で対応させます。
  • (3)ファクトリ(抽象ファクトリ):抽象ファクトリクラスでは、ファクトリメソッド(ファクトリメソッド)が製品を返すように宣言されています。抽象ファクトリはファクトリメソッドパターンのコアであり、オブジェクトを作成するすべてのファクトリクラスはこのインターフェイスを実装する必要があります。
  • (4)ConcreteFactory(コンクリートファクトリ):抽象ファクトリクラスのサブクラスであり、クライアントによって呼び出され、具象製品クラスのインスタンスを返す、抽象ファクトリで宣言されたファクトリメソッドを実装します。

2.3ファクトリメソッドパターンの拡張

2.3.1構成ファイルとリフレクション

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<appSettings>
		<add key="factory" value="FactoryMethodPattern.FileLoggerFactory"/>
	</appSettings>
</configuration>

このファイルでは、FactoryMethodSarmpleはファクトリクラスが配置されている名前空間の名前であり、FileLoggerFactoryは具象ファクトリクラスの名前です。.NETでは、構成ファイルは通常、App.config、Web.configなどの拡張子としてconfigを使用します。

以下は、.NETのリフレクションメカニズムの簡単な紹介です。
リフレクションは.NETの重要なメカニズムの1つです。リフレクションを通じて、.NETのすべてのタイプ(クラス、構造、デリゲート、インターフェイス、列挙など)を使用できます。実行時に取得されます。)メソッド、プロパティ、イベント、コンストラクターなどを含むメンバー。各メンバーの名前、修飾子、およびパラメーターを取得することもできます。コンストラクターの情報を取得するため、コンパイル時にオブジェクトの種類が不明な場合でも、クラス名で直接オブジェクトを作成できます。
タイプメタデータ情報は.NETアセンブリ(アセンブリ)にカプセル化されているため、最初にアセンブリのLoad( "アセンブリ名")メソッドを使用してアセンブリをロードし、次にそのCrcateInstance( "namespace.class")を使用できます。クラス名に応じたobject型のオブジェクトであり、ユーザーは必要に応じて必要な型に変換できます。概略コードは次のとおりです。

using System.Reflleetioe; //导入配置管理命名空间
object obj = Assemibly.Load["程序集名称”).CreateInatance("命名空间.类”);

 システム構成入入【System.Configuration.ConfigurationManager】、https: //www.nuget.org/packages/System.Configuration.ConfigurationManager

Install-Package System.Configuration.ConfigurationManager -Version 5.0.0

上記のコードでは、「namespace.class」を構成ファイルに格納できます。構成ファイルに格納されているクラス名文字列は、ConfigurationManagerクラスのappSettingsプロパティを使用して取得できます。
構成ファイルとリフレクションメカニズムを導入した後、クライアントテストコードでは、newキーワードを直接使用して特定のファクトリクラスを作成する必要はありませんが、特定のファクトリクラスのクラス名を構成ファイルに入れてから読み取ります。構成ファイルとオブジェクトを動的に作成するためのリフレクションメカニズムにより、クライアントコードは次のように変更されます。

//xml配置文件与反射方式扩展
// 1.读取【App.config】配置文件
string factoryString = ConfigurationManager.AppSettings["factory"];
// 参数"FactoryMethodPattern"是工厂类所在的命名空间的名称,"FactoryMethodPattern.FileLoggerFactory" 具体工厂类类名
LoggerFactory factory = (LoggerFactory)Assembly.Load("FactoryMethodPattern").CreateInstance(factoryString);
Logger logger = factory.CreateLogger();
logger.WriteLog();

2.3.2ファクトリメソッドパターンのオーバーロード

抽象ファクトリクラスLoggerFactoryで変更されたコードは次のとおりです。

/// <summary>
/// 日志记录器工厂接口,充当抽象工厂角色
/// </summary>
interface LoggerFactory
{
    /* 抽象工厂方法,实现方法重载 */
    Logger CreateLogger();
    Logger CreateLogger(string args);
    Logger CreateLogger(object obj);
}

対応する具象ファクトリクラスは、抽象ファクトリに対応するメソッドも実装します。これらのメソッドには、製品オブジェクトのさまざまな作成要件を満たすために、さまざまなビジネスロジックを含めることができます。

class DatabaseLoggerFactory : LoggerFactory
{
    public Logger CreateLogger()
    {
        //连接数据库,代码省略
        //创建数据库日志记录器对象
        Logger logger = new DatabaseLogger();
        //初始化日志记录器代码省略
        return logger;
    }

    public Logger CreateLogger(string args)
    {
        //使用参数 args 作为连接字符串链接数据库,代码省略
        Logger logger = new DatabaseLogger();
        //初始化数据库日志记录器,代码省略
        return logger;
    }

    public Logger CreateLogger(object obj)
    {
        //使用参数 obj 中的连接字符串链接数据库,代码省略
        Logger logger = new DatabaseLogger();
        //使用封装在参数 obj 中的数据来初始化数据库日志记录器,代码省略
        return logger;
    }
}

上記はDatabaseLoggerFactoryファクトリであり、FileLoggerFactoryも抽象ファクトリに対応するオーバーロードメソッドです。ここではアイデアを説明し、コードのデモンストレーションは上記と同様であるため、詳しく説明しません。

2.3.3ファクトリメソッドの非表示(簡略化)

クライアントの使用を簡素化するために、ファクトリメソッドをクライアントから非表示にすることもできます。この場合、productクラスのビジネスメソッドはファクトリクラスで直接呼び出され、ファクトリメソッドは呼び出す必要がありません。クライアントで呼び出されて製品オブジェクトを作成します。ファクトリオブジェクトを使用するだけです。作成された製品オブジェクトでビジネスメソッドを呼び出します。コードは次のように変更されます。

abstract class LoggerFactory 
{
    public void WriteLog() 
    {
        Logger logger = this.CreateLogger();
        logger.WriteLog();
    }

    public abstract Logger CreateLogger();
}

クライアント呼び出しメソッドは次のように変更されます。

//xml配置文件与反射方式扩展
// 1.读取【App.config】配置文件
string factoryString = ConfigurationManager.AppSettings["factorySimplified"];
// 参数"FactoryMethodPattern"是工厂类所在的命名空间的名称,"FactoryMethodPattern.Simplified.FileLoggerFactory" 具体工厂类类名
Simplified.LoggerFactory factory = (Simplified.LoggerFactory)Assembly.Load("FactoryMethodPattern").CreateInstance(factoryString);
factory.WriteLog(); //直接适用工厂对象来调用产品对象的业务方法

ファクトリモードの簡略版を次に示します。上記の2.3.2の完全モードと比較するために、構成ファイルを次のように変更します。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<appSettings>
		<add key="factoryFull" value="FactoryMethodPattern.Full.FileLoggerFactory"/>
		<add key="factorySimplified" value="FactoryMethodPattern.Simplified.DatabaseLoggerFactory"/>
	</appSettings>
</configuration>

クライアントプログラムのMain関数は、名前空間を導入し、エイリアスを変更します。

using System;
using System.Reflection; //反射
using System.Configuration; //配置管理
using Full = FactoryMethodPattern.Full; //工厂模式完整版本
using Simplified = FactoryMethodPattern.Simplified; //工厂模式简化版本

完全なコード例: 中FactoryMethodPatternプロジェクトhttps://gitee.com/dolayout/DesignPatternOfCSharp

3 |ファクトリモデルと適用可能な環境の長所と短所

ファクトリパターンは、シンプルファクトリパターンの拡張であり、シンプルファクトリパターンの利点を継承すると同時に、シンプルファクトリパターンの欠点を補います。ファクトリメソッドパターンは、最も頻繁に使用されるデザインパターンの1つであり、多くのオープンソースフレームワークとAPIライブラリのコアパターンです。

3.1ファクトリメソッドパターンの主な利点は次のとおりです。

  • (1)ファクトリメソッドモデルでは、ファクトリメソッドを使用して顧客が必要とする製品を作成し、インスタンス化される特定の製品カテゴリの詳細を顧客から非表示にします。ユーザーはファクトリのみを気にする必要があります。目的の製品に対応します。ただし、作成の詳細を気にする必要はなく、特定の製品カテゴリの名前を知る必要もありません。
  • (2)ファクトリロールと製品ロールに基づくポリモーフィックデザインは、ファクトリメソッドパターンの鍵です。これにより、ファクトリは作成する製品オブジェクトを個別に決定でき、このオブジェクトの作成方法の詳細は、具体的なファクトリに完全にカプセル化されます。ファクトリメソッドパターンは、すべての具象ファクトリクラスが同じ抽象親クラスを持っているため、ポリモーフィックファクトリパターンと呼ばれます。
  • (3)ファクトリメソッドパターンを使用するもう1つの利点は、システムに新しい製品を追加するときに、抽象ファクトリと抽象製品によって提供されるインターフェイスを変更する必要がなく、クライアントを変更する必要がなく、変更する必要がないことです。他の特定の工場や特定の製品を変更しますが、特定の工場や特定の製品を追加するだけです。このようにして、システムのスケーラビリティが非常に良くなり、開閉の原則に完全に準拠します。

3.2ファクトリメソッドパターンの主な欠点は次のとおりです。

  • (1)新製品を追加する場合は、特定の製品カテゴリを新規作成し、対応する特定の工場カテゴリを指定する必要があります。システム内のカテゴリ数がペアで増加するため、システムがある程度複雑になります。 。より多くのクラスをコンパイルして実行する必要があります。これにより、システムに追加のオーバーヘッドが発生します。
  • (2)システムのスケーラビリティを考慮すると、クライアントコードで定義されている抽象化レイヤーを導入する必要があります。これにより、システムの抽象化と理解が困難になります。

3.3ファクトリメソッドパターンの適用環境

  • (1)クライアントは必要なオブジェクトのクラスを知りません。ファクトリメソッドパターンでは、クライアントフィールドは特定の製品クラスのクラス名を知る必要はなく、対応するファクトリのみを知る必要があります。特定の製品オブジェクトが決定されます。特定のファクトリクラスごとに作成します。特定のファクトリクラスのクラス名を構成ファイルまたはデータベースに保存できます。
  • (2)抽象ファクトリクラスは、そのサブクラスを介して作成するオブジェクトを指定します。ファクトリメソッドパターンでは、抽象ファクトリクラスは製品を作成するためのインターフェイスを提供するだけでよく、そのサブクラスは、プログラムでオブジェクト指向ポリモーフィズムとリヒター置換の原理を使用して、作成する特定のオブジェクトを決定します。サブクラスオブジェクトは親オブジェクトを上書きし、システムの拡張を容易にします。

おすすめ

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