コンテンツ
シンプルファクトリパターン(静的ファクトリパターン)シンプルファクトリ
ファクトリパターン
機能:作成者と呼び出し元の分離を実現し、オブジェクトのインスタンス化に役立ちます。
コアエッセンス:新しい操作の代わりにファクトリを使用してオブジェクトをインスタンス化します
実装クラスを選択し、統合された管理と制御のためのオブジェクトを作成します。これにより、呼び出し元を実装クラスから切り離します。
ファクトリパターンは典型的なデカップリングパターンです
OOPの7つの原則を満たします。
オープンクローズ原則
依存性逆転の原則
デメテルの法則(それをうまく量る)
分類:
単純なファクトリパターン:同じ階層構造で任意の製品を生成するために使用されます(新しい製品を追加するには、既存のコードを拡張する必要があります)。
ファクトリメソッドパターン:同じ階層構造で固定製品を生成するために使用されます(任意の製品の追加をサポートします)。
抽象ファクトリパターン:スーパーファクトリの周りに他のファクトリを作成します。
適用可能なシナリオ:クラス作成パターンとして、ファクトリメソッドパターンは、複雑なオブジェクトを生成する必要がある場所ならどこでも使用できます。注意すべき点の1つは、複雑なオブジェクトはファクトリパターンの使用に適していますが、単純なオブジェクト、特にnewでのみ作成できるオブジェクトは、ファクトリパターンを使用する必要がないことです。システムのスケーラビリティを向上させる必要がある場合は、ファクトリモードを検討し、さまざまな製品をさまざまな実装ファクトリで組み立てます。
実際、作成パターンはクラスのインスタンス化プロセスを抽象化し、ソフトウェアモジュール内のオブジェクトの作成と使用を分離できます。
作成パターンは、ソフトウェア設計者に、何を作成するか(What)、誰が作成するか(Who)、いつ作成するか(When)に関して可能な限りの柔軟性を提供します。
シンプルファクトリパターン(静的ファクトリパターン)シンプルファクトリ
ファクトリクラスを作成して、同じインターフェイスを実装するいくつかのクラスのインスタンスを作成します。
単純なファクトリパターンでの役割は、ファクトリ、製品、クライアントです。次の例を参照してください。
まず、クラス図を見ることができます
具体的な実装コードは次のとおりです。
車のインターフェースを作成する
public interface Car {
public void name();
}
2つの実装クラスを作成する
public class WuLing implements Car{
@Override
public void name() {
System.out.println("五菱宏光");
}
}
public class Tesla implements Car{
@Override
public void name() {
System.out.println("特斯拉");
}
}
ファクトリクラスを作成する
public class CarFactory{
public static Car getCar(String car) {
if(car.equals("五菱")) {
return new WuLing();
}else if(car.equals("特斯拉")) {
return new Tesla();
}else {
return null;
}
}
}
テストする
public class Comsumer {
public static void main(String[] args){
Car car1 = CarFactory.getCar("五菱");
Car car2 = CarFactory.getCar("特斯拉");
car1.name();
car2.name();
}
}
出力の結果:
車がどうなったか心配する必要はありません。名前を付けて工場から持っていくだけです。
このモードの欠点をはっきりと感じることができます。Carインターフェースの実装クラスを追加してフォルクスワーゲン車を追加する場合は、工場でgetCar()メソッドを変更する必要があります。これは、オープンクローズの原則に違反します。
もちろん、ファクトリクラスのメソッドを変更して、パラメータを入力しなくても必要なものを取得できます。
public class CarFactory{
public static Car getWuLing(){
return new WuLing();
}
public static Car getTesla(){
return new Tesla();
}
}
実際、これは私たちのニーズを満たしていません。コードを変更する必要がありますが、前の方法のようにコードロジックで変更されることはありません。
単純なファクトリパターンの問題:
オープンクローズ原則に違反している
高い凝集度の責任分散の原則に違反して、すべての作成ロジックが1つのファクトリクラスに集中化されます
ファクトリメソッドパターンファクトリメソッド
ファクトリメソッドパターンは、単純なファクトリパターンをさらに分離したものです。これは、ビジネスコードのために巨大であった単純なファクトリクラスを個々のファクトリクラスに分割して、コードが同じクラスに結合されないようにすることと同じです。の。
ファクトリメソッドパターンとシンプルファクトリパターンはどちらもファクトリを介してオブジェクトを作成しますが、両者の最大の違いは、ファクトリメソッドパターンが設計の「オープンクローズ原則」に完全に準拠していることです。
例を見てください:
特定のコードは次のように実装されます。
車のインターフェース、Teslaクラス、WuLingクラスは変更されていません
自動車工場のインターフェースを作成する
public interface CarFactory{
public Car getCar();
}
自動車ファクトリインターフェイスの実装クラスTeslaFactoryファクトリクラスとWuLingFactoryクラスを作成します
public class TeslaFactory implements CarFactory{
@Override
public Car getCar(){
return new Tesla();
}
}
public class WuLingFactory implements CarFactory{
@Override
public Car getCar(){
return new WuLing();
}
}
最終試験
public class Comsumer {
public static void main(String[] args){
Car car1 = new WuLingFactory.getCar();
Car car2 = new TeslaFactory.getCar();
car1.name();
car2.name();
}
}
ここでの例はパラメータの問題を含まないため、私たちの気持ちはあまり明白ではありません。想像してみてください。TeslaクラスまたはWuLingクラスに多くのパラメータがある場合はどうでしょうか。このメソッドは消費者に優しいものです。車の製造方法を気にする必要はありません。対応するファクトリメソッドがインスタンス化します。ファクトリでメソッドを呼び出すだけです。
ここでは、狂った神のフローチャートがより明確になると思います(レイヤーを追加)
ファクトリメソッドパターンは、次の状況で使用できます。
クラスは、必要なオブジェクトのクラスを認識していません。
クラスは、そのサブクラスを介して作成するオブジェクトを指定します
アドバンテージ:
オブジェクトを作成したい呼び出し元は、その名前を知っているだけで済みます。
高いスケーラビリティ。製品を追加する場合は、ファクトリクラスを拡張するだけで済みます。
製品の特定の実装はシールドされており、発信者は製品のインターフェースのみを気にします。
欠点:
製品を追加するたびに、具象クラスとオブジェクト実装ファクトリを追加する必要があります。これにより、システム内のクラス数が2倍になり、システムの複雑さがある程度増し、システムの具象クラスの依存度も高まります。 。これは良いことではありません。
抽象ファクトリパターン
抽象ファクトリパターンはファクトリメソッドパターンに相対的です。つまり、ファクトリメソッドパターンは1つの製品シリーズ用であり、抽象ファクトリパターンは複数の製品シリーズ用です。
定義:抽象ファクトリパターンは、具体的なクラスを指定せずに、一連の関連オブジェクトまたは相互依存オブジェクトを作成するためのインターフェイスを提供します。抽象ファクトリパターンはファクトリのファクトリです
個人的には、別のレイヤーを追加することを意味すると思います。もちろん、これは私の個人的な意見です。
ケースを説明する前に、製品ファミリと製品レベルの2つの概念を知っておく必要があります。
次に、特定のケースを見てみましょう。
まず、電話インターフェースとルーターインターフェースを作成します
//手机产品接口
public interface IPhoneProduct {
void start();
void shutdown();
void callup();
void sendSMS();
}
//路由器产品接口
public interface IRouterProduct {
void start();
void shutdown();
void openWifi();
void setting();
}
次に、携帯電話インターフェースの2つの実装クラスを作成します。Xiaomi携帯電話とHuawei携帯電話です。
//小米手机
public class XiaoMiPhone implements IPhoneProduct{
@Override
public void start() {
System.out.println("开启小米手机");
}
@Override
public void shutdown() {
System.out.println("关闭小米手机");
}
@Override
public void callup() {
System.out.println("小米手机打电话");
}
@Override
public void sendSMS() {
System.out.println("小米手机发短信");
}
}
//华为手机
public class HuaWeiPhone implements IPhoneProduct{
@Override
public void start() {
System.out.println("开启华为手机");
}
@Override
public void shutdown() {
System.out.println("关闭华为手机");
}
@Override
public void callup() {
System.out.println("华为手机打电话");
}
@Override
public void sendSMS() {
System.out.println("华为手机发短信");
}
}
XiaomiルーターとHuaweiルーターの2つのルーターインターフェイスの実装クラスを作成します
//小米路由器
public class XiaoMiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("启动小米路由器");
}
@Override
public void shutdown() {
System.out.println("关闭小米路由器");
}
@Override
public void openWifi() {
System.out.println("小米路由器打开WiFi");
}
@Override
public void setting() {
System.out.println("小米路由器设置");
}
}
//华为路由器
public class HuaWeiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("启动华为路由器");
}
@Override
public void shutdown() {
System.out.println("关闭华为路由器");
}
@Override
public void openWifi() {
System.out.println("华为路由器打开WiFi");
}
@Override
public void setting() {
System.out.println("华为路由器设置");
}
}
製造する抽象的な製品工場を書く
//抽象产品工厂
public interface IProductFactory {
//生产手机
IPhoneProduct iphoneProduct();
//生产路由器
IRouterProduct irouterProduct();
}
抽象製品ファクトリの実装クラスを作成します
//小米工厂
public class XiaoMiFactory implements IProductFactory {
@Override
public IPhoneProduct iphoneProduct() {
return new XiaoMiPhone();
}
@Override
public IRouterProduct irouterProduct() {
return new XiaoMiRouter();
}
}
//华为工厂
public class HuaWeiFactory implements IProductFactory {
@Override
public IPhoneProduct iphoneProduct() {
return new HuaWeiPhone();
}
@Override
public IRouterProduct irouterProduct() {
return new HuaWeiRouter();
}
}
クライアントテストを作成します。
public class Client {
public static void main(String[] args) {
System.out.println("**********华为系列***********");
//华为工厂
HuaWeiFactory huaweiFactory = new HuaWeiFactory();
IPhoneProduct huaweiPhone = huaweiFactory.iphoneProduct();
huaweiPhone.start();
huaweiPhone.callup();
}
}
演算結果:
適用可能なシナリオ:クライアント(アプリケーション層)は、製品クラスインスタンスの作成方法と実装方法の詳細に依存しません。一連の関連する製品オブジェクト(同じ製品ファミリーに属する)を一緒に使用して、製品クラスのライブラリを提供するために多くの反復コードを必要とするオブジェクトを作成することを強調します。すべての製品は同じインターフェイスで表示されるため、クライアントは特定の実装に依存しない
アドバンテージ:
アプリケーション層での特定の製品のコード分離、作成の詳細を気にする必要はありません
一緒に製品のファミリーを作成する
欠点:
作成できるすべての可能な製品セット、および製品ファミリーで新製品を拡張することの難しさを指定します。
システムの抽象化と理解の難しさを増します
まとめ
単純なファクトリパターン:設計原則にある程度準拠していませんが、実際に最も使用されています
ファクトリメソッドパターン:既存のクラスを変更せずに新しいファクトリクラスを追加して拡張
抽象ファクトリパターン:製品を追加することはできません。製品ファミリを追加できます
(ジョーク:レイヤーを追加しても解決できないものはありません)
調査の最後に、カートを馬の前に置かないという1つのことを明確に知る必要があります。特定のデザインパターンを使用するのではなく、ソフトウェアをより適切に設計するためのデザインパターンを学習します。