[設計モード]工場方法


Factory Method


背景


ファクトリメソッドは、親クラスでオブジェクトを作成するインタフェースを提供する設計モードの1つです.サブクラスは、オブジェクトの作成時にシェイプを変換できます.

💀 問題の定義


物流管理アプリケーションの作成を想定します.アプリケーションの最初のバージョンはトラック輸送のみに関連するため、アプリケーションのコードはTruckクラスにあります.
やがてこのアプリが有名になり、多くの人が海運会社に海運支援を求めた.

Truckクラスに既に密接に関連付けられているコードにShipsを追加して変更するのは容易ではありません.
拡張性の悪いコードに問題があります.

😊 ソリューション


この場合,工場メソッド設計モードでは,newによってオブジェクトを生成する部分の代わりに特殊な工場メソッドを呼び出すことを提案する.すなわち,オブジェクトはファクトリメソッドでnewによって作成される.ファクトリメソッドによって生成されるオブジェクトを製品と呼ぶ.


効果:ファクトリメソッドで、サブクラスで作成したオブジェクトのタイプを変更できます.
Logistics l=new RoadLogistics(); or new SeaLogistics(); 
Transtport t=l.createTransport();
t.deliver()
  • の条件に従って海運、トラック輸送を決定し、工場方法によって状況に合致する対象を生成する.
  • 生成された
  • の部分を分離するだけであるため、プライマリロジックは、コードを繰り返さずに既存の配信メソッド呼び出し部分を使用することができるため、影響を受けない.

  • 輸送手段のデリバリ部分は、Transportインタフェースにおいてデリバリ方法を定義し、サブクラスによって実装される.
  • 工場法によって生産された製品は、抽象チェーン伝送と見なされる.したがって,球状体が多く増加してもコード的には変化しない.
  • 🧱 こうぞう



  • 工場の方法で作られた製品部分.工場メソッドに基づいて作成されたすべてのオブジェクトに適したフィーチャーに基づいて、製品インタフェースを定義します.

  • 「秘密製品」は、それぞれの製品インタフェースを実装しています.

  • Creatorクラス宣言Productオブジェクトを作成するファクトリメソッド.メソッドの戻りタイプが製品と一致することが重要です.

  • ファクトリメソッドを抽象化し,Creatorのサブクラスにそれぞれのバージョンでメソッドを実装させることもできる.あるいはbasefactoryメソッドがデバッガバージョンを返すのも方法です.

  • Creatorの名前を見て誤解すべきではないのは、製品の作成がCreatorのライフサイクル機能ではないことです.通常、Creatorクラスには、既存の製品に関連するコアビジネスロジックがあります.ファクトリ・メソッドを使用すると、このロジックを機密製品から分離できます.

  • Concrete CreatorsはCreatorクラスの基本ファクトリメソッドを継承し、他のタイプの製品を返します.
  • は必ずしもそうではなく、ファクトリメソッドは新しいバージョンのインスタンスを生成する必要はありません.キャッシュやオブジェクトプールなどの既存のオブジェクトを返すこともできます.
  • 🙋 いつ使いますか。


  • ビジネスロジックを書き直すたびにシステムリソースを節約するのではなく、既存のオブジェクトを再使用します.

  • 既存のオブジェクトを再使用するプロセス
    1.作成したすべてのオブジェクトを追跡するリポジトリを作成
    2.誰かがオブジェクトを要求した場合、プログラムはpoolでfree objectを検索します.
    3. return
    4.ない場合はnewでpoolを作成または登録する

  • このロジックはクラスの作成者部分に配置するのに適していますが、作成者はnew objectsを返さなければなりません.既存のオブジェクトを返すことができません.

  • したがって、ファクトリメソッドを使用して、この2つのメソッドを作成/再使用できます.

  • コードに関連付けられたオブジェクトの正確なタイプ、関連付け、依存関係は予め知られていない.
  • ファクトリメソッドは、製品を使用するロジックと、製品を生成するロジックとを分離する.したがって、既存のコードにかかわらず、製品の拡張に有利です.

  • ライブラリまたはフレームワーク内のユーザーに内部コンポーネントを拡張する方法を提供します.
  • 🔪 メリットとデメリット


    1.メリット

  • 生成部分とコンクリート製品との間の強い結合を回避することができる.
  • 単一責任原則(SRP)を遵守する.生成された部分を1つの場所に移動して、一部の修正が他の部分の修正に影響を与えないようにします.
  • Open/Closed Principle(OCP). 既存のコードを変更することなく、新しいタイプの製品を適用できます.拡張に長けている.
  • 2.短所

  • このモードを実装するために多くのサブクラスが追加され、コードがより複雑になる可能性があります.
  • 📝 例


    Shape.java
    public interface Shape{
    	void draw();
    }
    Circle.java
    public class Circle implements Shape{
    	@Override
        public void draw(){
        	System.out.println("Inside Circle::draw() method.");
        }
    }
    Rectangle.java
    public class Circle implements Shape{
    	@Override
        public void draw(){
        	System.out.println("Inside Rectangle::draw() method.");
        }
    }
    Square.java
    public class Circle implements Shape{
    	@Override
        public void draw(){
        	System.out.println("Inside Square::draw() method.");
        }
    }
    ShapeFactory.java
    public class ShapeFactory{
    	public Shape getShape(String shapeType){
        	if(shapeType==null){
            	return null;
            }
            if(shapeType.equalsIgnoreCase("CIRCLE")){
            	return new Circle();
            } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
            	return new Rectangle();
            } else if(shapeType.equalsIgnoreCase("SQUARE")){
            	return new Square();
            }
            return null;
        }
    }
    FactoryPatternDemo.java
    public class FactoryPatternDemo{
    	public static void main(String[] args){
        	ShapeFactory shapeFactory=new ShapeFactory();
            
            Shape shape1=shapeFactory.getShape("CIRCLE");
            shape1.draw();
            
            Shape shape2=shapeFactory.getShape("RECTANGLE");
            shape1.draw();
            
            Shape shape3=shapeFactory.getShape("SQUAREa");
            shape1.draw();
            
        }
    }

    リファレンス


    Refactoring Guru
    サンプルコード