シングルトンパターン
核心点: クラスにインスタンスが 1 つだけあることを確認し、グローバル アクセス ポイントを提供します。
実際の開発では、構成情報クラスやスレッドプールクラスなど、クラスを 1 つのインスタンスのみに制限する必要がある状況によく遭遇します。この場合、シングルトン パターンを使用できます。シングルトン パターンでは、クラスのインスタンスが 1 つだけであることが保証され、グローバル アクセス ポイントが提供されるため、他のオブジェクトはこのアクセス ポイントを通じてクラスのインスタンスを取得できます。
シングルトン パターンを実装するときは、遅延アプローチまたはハングリー アプローチを使用できます。遅延スタイルは、インスタンスに初めてアクセスしたときにインスタンスがインスタンス化されるのに対し、ハングリー スタイルはクラスがロードされたときにインスタンスを作成することを意味します。
シングルトン パターンの簡単なコード例を次に示します。
public class Singleton {
private static Singleton instance;
private Singleton() {
// 私有构造方法,防止外部创建实例
}
public static Singleton getInstance() {
if (instance == null) {
// 第一次访问时才进行实例化
instance = new Singleton();
}
return instance;
}
// 其他方法...
}
アドバンテージ:
- これにより、インスタンスがグローバルに 1 つだけ存在することが保証され、システム リソースが節約されます。
- 他のオブジェクトがインスタンスを取得しやすくするためのグローバル アクセス ポイントを提供します。
- また、マルチスレッド環境ではインスタンスが 1 つだけ存在することが保証されます。
他の同様のモデルと比較してください:
- 単純なファクトリ パターンとファクトリ パターンでもオブジェクトを作成できますが、これらは主に、インスタンスが 1 つだけ存在することを保証するのではなく、オブジェクト作成の問題を解決するために使用されます。
- 抽象ファクトリ パターンは一連の関連オブジェクトを作成できますが、その目的はシングルトン パターンとは異なります。抽象ファクトリ パターンはオブジェクトのグループの作成に重点を置いているのに対し、シングルトン パターンは 1 つのインスタンスのみを必要とします。
- ビルダー パターンでもオブジェクトを作成できますが、インスタンスが 1 つだけ存在することを保証するよりも、構築プロセスと複雑なオブジェクトの表現に重点が置かれています。
概要: シングルトン パターンは一般的に使用される作成パターンであり、クラスのインスタンスが 1 つだけであることを保証し、インスタンスを簡単に取得するためのグローバル アクセス ポイントを提供します。シングルトン モードを使用するとシステム リソースを節約できますが、マルチスレッド環境では安全性に注意する必要があります。他の同様のパターンと比較することで、シングルトン パターンの利点と適用可能なシナリオをよりよく理解できます。
工場出荷時のパターン
中心となるアイデア: オブジェクトを作成するためのインターフェイスを定義しますが、どのクラスをインスタンス化するかはサブクラスに決定させます。
オブジェクト指向プログラミングでは、特定の共通の特性を持つ複数のオブジェクトを作成する必要がある状況がよくありますが、この場合、ファクトリ パターンを使用してオブジェクトの作成を管理できます。ファクトリ パターンはオブジェクトを作成するためのインターフェイスを定義しますが、作成されるオブジェクトの特定のクラスはサブクラスによって決定されます。
単純なファクトリ パターンのコード例を次に示します。
public interface Product {
void show();
}
public class ProductA implements Product {
@Override
public void show() {
System.out.println("This is product A.");
}
}
public class ProductB implements Product {
@Override
public void show() {
System.out.println("This is product B.");
}
}
public interface Factory {
Product createProduct();
}
public class FactoryA implements Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}
public class FactoryB implements Factory {
@Override
public Product createProduct() {
return new ProductB();
}
}
public class Client {
public static void main(String[] args) {
Factory factory = new FactoryA();
Product product = factory.createProduct();
product.show();
}
}
アドバンテージ:
- オブジェクトの作成と使用を分離すると、ユーザーはインターフェイスのみを気にし、特定の実装クラスについて気にする必要がなくなります。
- オープンとクローズの原則に従って、特定の製品を追加するときは、対応する特定の製品クラスとファクトリ クラスを記述するだけで済み、他のコードを変更する必要はありません。
他の同様のモデルと比較してください:
- 単純なファクトリ パターンでもオブジェクトを作成できますが、オブジェクト作成ロジックがファクトリ クラスに配置され、オープン/クローズの原則に違反します。
- シングルトン パターンでは、グローバルにインスタンスが 1 つだけ存在することが保証されるため、同じ特性を持つ複数のオブジェクトの作成には適していません。
- 抽象ファクトリ パターンは、一連の関連オブジェクトを作成するために使用されます。ファクトリ パターンとの違いは、抽象ファクトリ パターンがオブジェクトのセットの作成に重点を置いているということです。
概要: ファクトリ パターンは一般的に使用される作成パターンであり、オブジェクトを作成するためのインターフェイスを定義しますが、インスタンス化されるクラスはサブクラスによって決定されます。ファクトリ パターンを使用すると、開始と終了の原則に従って、オブジェクトの作成と使用を分離できます。他の同様のパターンと比較して、ファクトリ パターンはオブジェクトの作成プロセスにより注意を払い、特定の共通性を持つ複数のオブジェクトを作成する必要がある状況に適しています。
抽象的な工場パターン
中心となるアイデア: 一連の関連オブジェクトまたは相互依存オブジェクトを作成するためのインターフェイスを提供します。
Abstract Factory パターンは、特定のクラスを指定せずに、一連の関連オブジェクトまたは相互依存オブジェクトを作成するためのインターフェイスを提供する作成パターンです。
以下は、抽象ファクトリ パターンの簡単なコード例です。
public interface ProductA {
void show();
}
public class ConcreteProductA1 implements ProductA {
@Override
public void show() {
System.out.println("This is concrete product A1.");
}
}
public class ConcreteProductA2 implements ProductA {
@Override
public void show() {
System.out.println("This is concrete product A2.");
}
}
public interface ProductB {
void show();
}
public class ConcreteProductB1 implements ProductB {
@Override
public void show() {
System.out.println("This is concrete product B1.");
}
}
public class ConcreteProductB2 implements ProductB {
@Override
public void show() {
System.out.println("This is concrete product B2.");
}
}
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
public class Client {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.show();
productB1.show();
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.show();
productB2.show();
}
}
アドバンテージ:
- 単一責任の原則に準拠するように設計された、関連するオブジェクトまたは相互依存するオブジェクトのセットをまとめて作成します。
- クライアント コードは特定のファクトリ クラスから分離されているため、新しい製品ラインの拡張が容易になります。
他の同様のモデルと比較してください:
- ファクトリ パターンでもオブジェクトを作成できますが、その焦点は特定のクラスのオブジェクト作成プロセスにあるのに対し、抽象ファクトリ パターンは関連するオブジェクトまたは相互依存するオブジェクトのセットの作成に重点を置いています。
- シングルトン パターンでは、グローバルにインスタンスが 1 つだけ存在することが保証されるため、一連のオブジェクトの作成には適していません。
概要: 抽象ファクトリ パターンは、一般的に使用される作成パターンであり、特定のクラスを指定せずに、一連の関連オブジェクトまたは相互依存オブジェクトを作成するためのインターフェイスを提供します。抽象ファクトリ パターンは、関連するオブジェクトまたは相互依存するオブジェクトのセットを一緒に作成し、特定のファクトリ クラスからのクライアントの分離を実現します。他の同様のパターンと比較して、Abstract Factory パターンはオブジェクトのセットの作成に重点を置いています。
ビルダーパターン
中心的なアイデア: 複雑なオブジェクトの構築をその表現から分離し、同じ構築プロセスで異なる表現を作成できるようにします。
ビルダー パターンは、複雑なオブジェクトの構築をその表現から分離する作成パターンであり、同じ構築プロセスで異なる表現を作成できるようにします。
簡単なビルダー パターンのコード例を次に示します。
public class Product {
private String partA;
private String partB;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void show() {
System.out.println("Part A: " + partA);
System.out.println("Part B: " + partB);
}
}
public abstract class Builder {
public abstract void buildPartA();
public abstract void buildPartB();
public abstract Product getResult();
}
public class ConcreteBuilder1 extends Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.setPartA("Part A from ConcreteBuilder1");
}
@Override
public void buildPartB() {
product.setPartB("Part B from ConcreteBuilder1");
}
@Override
public Product getResult() {
return product;
}
}
public class ConcreteBuilder2 extends Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.setPartA("Part A from ConcreteBuilder2");
}
@Override
public void buildPartB() {
product.setPartB("Part B from ConcreteBuilder2");
}
@Override
public Product getResult() {
return product;
}
}
public class Director {
public void construct(Builder builder) {
builder.buildPartA();
builder.buildPartB();
}
}
public class Client {
public static void main(String[] args) {
Director director = new Director();
Builder builder1 = new ConcreteBuilder1();
director.construct(builder1);
Product product1 = builder1.getResult();
product1.show();
Builder builder2 = new ConcreteBuilder2();
director.construct(builder2);
Product product2 = builder2.getResult();
product2.show();
}
}
アドバンテージ:
- 複雑なオブジェクトの構築をその表現から分離すると、構築プロセスが柔軟になり、同じ構築プロセスに対して異なる表現を作成できます。
- クライアントは特定の構築プロセスを知る必要はなく、特定のビルダー オブジェクトを指定するだけでよいため、クライアントの使用が簡素化されます。
他の同様のモデルと比較してください:
- ファクトリ パターンはオブジェクトの作成にも使用されますが、それはオブジェクトの作成プロセスに重点を置いているのに対し、ビルダー パターンはオブジェクトの構築プロセスと表現に重点を置いています。
- Abstract Factory パターンでは、一連の関連オブジェクトを作成することもできます。これにより、関連オブジェクトのグループがまとめて作成されます。一方、Builder パターンでは、複雑なオブジェクトの構築とその表現が分離されます。
概要: ビルダー パターンは、複雑なオブジェクトの構築をその表現から分離する一般的に使用される作成パターンであり、構築プロセスを柔軟にし、同じ構築プロセスの異なる表現を作成できるようにします。ビルダー パターンを使用すると、複雑なオブジェクトの構築の問題をより適切に解決できると同時に、クライアント コードがより簡潔になり、保守が容易になります。他の同様のパターンと比較して、ビルダー パターンはオブジェクトの構築プロセスと表現に重点を置いています。
試作パターン
概要
プロトタイプ パターンは、既存のオブジェクトをコピーして新しいオブジェクトを作成し、初期化プロセスの繰り返しを回避する作成パターンです。基本的なアイデアは、clone メソッドを通じて既存のオブジェクトをコピーして、新しいオブジェクトを作成することです。プロトタイプ パターンは、多数の同様のオブジェクトを作成する必要があるが、オブジェクトの作成プロセスに時間や費用がかかる状況に適しています。
コード例
プロトタイプ パターンを使用したコード例を次に示します。
// 原型接口
interface Prototype {
Prototype clone(); // 克隆方法
}
// 具体原型类
class ConcretePrototype implements Prototype {
private String name;
public ConcretePrototype(String name) {
this.name = name;
}
@Override
public Prototype clone() {
return new ConcretePrototype(this.name);
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ConcretePrototype prototype = new ConcretePrototype("原型对象");
ConcretePrototype clone = (ConcretePrototype) prototype.clone();
clone.setName("克隆对象");
System.out.println(prototype.getName()); // 输出:原型对象
System.out.println(clone.getName()); // 输出:克隆对象
}
}
Prototype
上の例では、クローン メソッドを含むプロトタイプ インターフェイスを定義しましたclone()
。特定のプロトタイプ クラスは、ConcretePrototype
プロトタイプ インターフェイスを実装し、新しいオブジェクトが作成されて返される clone メソッドを実装します。クライアント コードは、プロトタイプ パターンを使用してプロトタイプ オブジェクトを作成し、clone メソッドを通じてクローン オブジェクトを取得します。
利点と欠点の分析
プロトタイプ モードの利点は次のとおりです。
- オブジェクトの初期化時間とリソースを節約します。プロトタイプ モードでは、既存のオブジェクトをクローンして新しいオブジェクトを作成するため、初期化プロセスの繰り返しが回避され、オブジェクトの作成効率が向上します。
- オブジェクト作成プロセスを簡素化します。プロトタイプ モードを使用すると、各プロパティの値を手動で設定することなく、既存のオブジェクトの状態を直接コピーできるため、オブジェクトの作成プロセスが簡素化されます。
プロトタイプパターンの欠点は次のとおりです。
- オブジェクトのクローン作成が制限される場合があります。一部のオブジェクトの複製は制限されています。たとえば、シングルトン オブジェクトは複製できない、シリアル化不可能なオブジェクトは複製できないなどです。
- オブジェクトのクローンを作成すると、ディープ コピーの問題が発生する可能性があります。オブジェクトのプロパティに参照型のメンバ変数が含まれる場合、クローン作成時にディープコピーの問題が発生する可能性があるため注意が必要です。
他のモードとの比較
- プロトタイプ パターンとファクトリー パターン: プロトタイプ パターンとファクトリー パターンはどちらも作成パターンですが、目的が異なります。プロトタイプ パターンは、既存のオブジェクトをコピーして新しいオブジェクトを作成する方法に焦点を当てますが、ファクトリ パターンは、ファクトリ メソッドまたはファクトリ クラスを通じてオブジェクトを作成する方法に焦点を当てます。
- プロトタイプ パターンとシングルトン パターン: プロトタイプ パターンとシングルトン パターンはどちらも作成パターンですが、目的はまったく異なります。プロトタイプ パターンは、それぞれが独立した状態を持つ新しいオブジェクトを作成することを目的としていますが、シングルトン パターンは、すべてが同じ状態を共有する一意のオブジェクトを作成することを目的としています。
つまり、プロトタイプ パターンは、既存のオブジェクトをコピーして新しいオブジェクトを作成する作成パターンであり、類似したオブジェクトを大量に作成する必要がある場合に適しています。これにより、オブジェクト作成の効率が向上し、オブジェクト作成プロセスが簡素化されます。ただし、オブジェクトのクローン作成とディープ コピーの問題の制限に注意する必要があります。
全体として、プロトタイプ パターンは、コードの再利用と作成効率を効果的に向上させることができるシンプルで実用的な設計パターンであり、さまざまなアプリケーション シナリオに適しています。