Mr.Raindrop

Mr.Raindrop

一切都在无可挽回的走向庸俗。
twitter
github

デザインパターン入門--生成に関するパターン

作成型パターン#

作成型パターン:オブジェクトを作成するためのパターンであり、インスタンス化のプロセスを抽象化します。オブジェクトの作成に焦点を当て、作成型パターンはオブジェクトの作成プロセスを抽象化し、オブジェクトの作成をカプセル化したものと理解できます。クライアントプログラムはオブジェクトを使用するだけで、オブジェクトの作成プロセスのロジックを気にする必要はありません。

シンプルファクトリーパターン#

シンプルファクトリーパターン(Simple Factory Pattern):静的ファクトリーメソッド(Static Factory Method)パターンとも呼ばれ、シンプルファクトリーパターンでは、異なるパラメータに基づいて異なるクラスのインスタンスを返すことができます(ボタンは形状パラメータに基づいて異なる形状を返します)。シンプルファクトリーパターンは、他のクラスのインスタンスを作成する責任を持つクラスを特別に定義し、作成されるインスタンスは通常共通の親クラスを持ちます。

image

実装方法#

  • ファクトリークラス(Factory):渡されたパラメータ(文字列、列挙型など)に基づいて対応する製品オブジェクトを作成します。

    public class VendorFactory {
        public static IVender createVendor(String type) {
            switch (type) {
                case "A": return new VendorA();
                case "B": return new VendorB();
                default: throw new RuntimeException("供給者が存在しません");
            }
        }
    }
    
  • 抽象製品(Abstract Product):すべての製品の共通インターフェースを定義します。

    public interface IVender {
        void order();
    }
    
  • 具体的な製品(Concrete Product):抽象製品インターフェースを実装するクラスであり、各クラスは一つの製品タイプに対応します。

    public class VendorA implements IVender {
        @Override
        public void order() { System.out.println("A供給者の注文が成功しました"); }
    }
    

使用#

IVender vendor = VendorFactory.createVendor("A");
vendor.order();  // 出力:A供給者の注文が成功しました

ファクトリーメソッドパターン#

コアの考え方は、オブジェクトの作成プロセスを抽象化し、サブクラスがどの具体的なクラスをインスタンス化するかを決定できるようにすることです。これにより、クライアントコードを変更することなくシステム機能を拡張できます。

構成要素#

  • 抽象ファクトリー(Creator)
  • 具体的なファクトリー(Concrete Creator)
  • 抽象製品(Product)
  • 具体的な製品(Concrete Product)

実装#

// 抽象製品
interface Car {
    void show();
}

// 具体的な製品
class CarA implements Car {
    @Override
    public void show() { System.out.println("小米SU7"); }
}

// 抽象ファクトリー
abstract class Factory {
    public abstract Car createCar();
}

// 具体的なファクトリー
class CarFactoryA extends Factory {
    @Override
    public Car createCar() { return new CarA(); }
}

../_images/SimpleFactory.jpg

実装方法#

  • ファクトリークラス(Factory):渡されたパラメータ(文字列、列挙型など)に基づいて対応する製品オブジェクトを作成します。

    public class VendorFactory {
        public static IVender createVendor(String type) {
            switch (type) {
                case "A": return new VendorA();
                case "B": return new VendorB();
                default: throw new RuntimeException("供給者が存在しません");
            }
        }
    }
    
  • 抽象製品(Abstract Product):すべての製品の共通インターフェースを定義します。

    public interface IVender {
        void order();
    }
    
  • 具体的な製品(Concrete Product):抽象製品インターフェースを実装するクラスであり、各クラスは一つの製品タイプに対応します。

    public class VendorA implements IVender {
        @Override
        public void order() { System.out.println("A供給者の注文が成功しました"); }
    }
    

使用#

IVender vendor = VendorFactory.createVendor("A");
vendor.order();  // 出力:A供給者の注文が成功しました

ファクトリーメソッドパターン#

コアの考え方は、オブジェクトの作成プロセスを抽象化し、サブクラスがどの具体的なクラスをインスタンス化するかを決定できるようにすることです。これにより、クライアントコードを変更することなくシステム機能を拡張できます。

構成要素#

  • 抽象ファクトリー(Creator)
  • 具体的なファクトリー(Concrete Creator)
  • 抽象製品(Product)
  • 具体的な製品(Concrete Product)

実装#

// 抽象製品
interface Car {
    void show();
}

// 具体的な製品
class CarA implements Car {
    @Override
    public void show() { System.out.println("小米SU7"); }
}

// 抽象ファクトリー
abstract class Factory {
    public abstract Car createCar();
}

// 具体的なファクトリー
class CarFactoryA extends Factory {
    @Override
    public Car createCar() { return new CarA(); }
}

抽象ファクトリーパターン#

一般的に、具体的なファクトリーには一つのファクトリーメソッドまたは一組のオーバーロードされたファクトリーメソッドしかありません。しかし、時には一つのファクトリーが単一の製品オブジェクトではなく、複数の製品オブジェクトを提供する必要があります。

適用条件

システムが提供するファクトリーが生産する具体的な製品が単純なオブジェクトではなく、異なる製品階層に属する異なるタイプの具体的な製品である場合、抽象ファクトリーパターンを使用する必要があります。

ファクトリーメソッドパターンは一つの製品階層に対して対応しますが、抽象ファクトリーパターンは複数の製品階層に対処する必要があります。一つのファクトリー階層が異なる製品階層の製品オブジェクトの作成を担当できる場合、抽象ファクトリーパターンはファクトリーメソッドパターンよりもシンプルで効率的です。

パターン構造#

  • AbstractFactory:抽象ファクトリー
  • ConcreteFactory:具体的なファクトリー
  • AbstractProduct:抽象製品
  • Product:具体的な製品

image

[](抽象工厂模式(通俗易懂)_抽象工厂 通俗的方式 - CSDN 博客)

image

プロトタイプパターン#

既存のオブジェクト(プロトタイプ)をコピーして新しいオブジェクトを作成することによって、従来のコンストラクタを使用せずにインスタンス化します。これは、複雑なオブジェクトを効率的に作成する必要があるシーンや、同じタイプのオブジェクトを動的に生成するシーンに特に適しています。

構成#

  • 抽象プロトタイプ(Prototype):クローンメソッドのインターフェースを定義します(例えば、Cloneableインターフェース)。
  • 具体的なプロトタイプ(Concrete Prototype):クローンロジックを実装する具体的なオブジェクト(例えば、clone()メソッドをオーバーライドします)。
  • クライアント(Client):プロトタイプオブジェクトのクローンメソッドを呼び出して新しいオブジェクトを作成します。

クローン方法:浅いコピー、深いコピー(実装またはシリアル化による)。

実装#

// 抽象プロトタイプ(Cloneableインターフェースを実装)
public abstract class Shape implements Cloneable {
    protected String type;
    public abstract void draw();

    @Override
    public Shape clone() {
        try {
            return (Shape) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();  // 発生しない
        }
    }
}

// 具体的なプロトタイプ:円
public class Circle extends Shape {
    public Circle() {
        type = "Circle";
    }

    @Override
    public void draw() {
        System.out.println("円を描画");
    }
}

// クライアント呼び出し
Shape original = new Circle();
Shape clone = original.clone();  // クローンオブジェクト
clone.draw();  // 出力:円を描画

シングルトンパターン#

クラスがアプリケーションのライフサイクル全体で一つのインスタンスしか持たないことを保証し、グローバルなアクセス点を提供します。シングルトンパターンを使用することで、複数のインスタンスによるリソースの浪費やデータの不整合の問題を回避できます。

シングルトンを保証する方法:

クラス自身がその唯一のインスタンスを保持する責任を持たせます。このクラスは他のインスタンスが作成されないことを保証し、そのインスタンスにアクセスするためのメソッドを提供できます。これがシングルトンパターンの動機です。

image

実装方法#

シングルトンパターン - 知乎

遅延初期化(最初の呼び出し時に作成される)

public class Singleton {
    private static Singleton instance;

    private Singleton() {
        // プライベートコンストラクタ
    }

    public static Singleton getInstance() {
        if (instance == null) { // 最初のチェック
            instance = new Singleton();
        }
        return instance;
    }
}

早期初期化(クラスがロードされるときにインスタンスが作成される)

public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {
        // プライベートコンストラクタ
    }

    public static Singleton getInstance() {
        return instance;
    }
}
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。