作成型パターン#
作成型パターン:オブジェクトを作成するためのパターンであり、インスタンス化のプロセスを抽象化します。オブジェクトの作成に焦点を当て、作成型パターンはオブジェクトの作成プロセスを抽象化し、オブジェクトの作成をカプセル化したものと理解できます。クライアントプログラムはオブジェクトを使用するだけで、オブジェクトの作成プロセスのロジックを気にする必要はありません。
シンプルファクトリーパターン#
シンプルファクトリーパターン(Simple Factory Pattern):静的ファクトリーメソッド(Static Factory Method)パターンとも呼ばれ、シンプルファクトリーパターンでは、異なるパラメータに基づいて異なるクラスのインスタンスを返すことができます(ボタンは形状パラメータに基づいて異なる形状を返します)。シンプルファクトリーパターンは、他のクラスのインスタンスを作成する責任を持つクラスを特別に定義し、作成されるインスタンスは通常共通の親クラスを持ちます。
実装方法#
-
ファクトリークラス(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(); }
}
実装方法#
-
ファクトリークラス(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:具体的な製品
[例](抽象工厂模式(通俗易懂)_抽象工厂 通俗的方式 - CSDN 博客)
プロトタイプパターン#
既存のオブジェクト(プロトタイプ)をコピーして新しいオブジェクトを作成することによって、従来のコンストラクタを使用せずにインスタンス化します。これは、複雑なオブジェクトを効率的に作成する必要があるシーンや、同じタイプのオブジェクトを動的に生成するシーンに特に適しています。
構成#
- 抽象プロトタイプ(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(); // 出力:円を描画
シングルトンパターン#
クラスがアプリケーションのライフサイクル全体で一つのインスタンスしか持たないことを保証し、グローバルなアクセス点を提供します。シングルトンパターンを使用することで、複数のインスタンスによるリソースの浪費やデータの不整合の問題を回避できます。
シングルトンを保証する方法:
クラス自身がその唯一のインスタンスを保持する責任を持たせます。このクラスは他のインスタンスが作成されないことを保証し、そのインスタンスにアクセスするためのメソッドを提供できます。これがシングルトンパターンの動機です。
実装方法#
遅延初期化(最初の呼び出し時に作成される)
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;
}
}