これはデザインパターンシリーズの第 2 回であり、ビルダーデザインパターンです。私は記事をシリーズとして配信したいので、できるだけ同じ執筆スタイルを維持し、私の理解を明確に説明しようとします。ビルダーデザインパターンについては、以下のようないくつかの側面から学ぶことができます。
- 概要
- 本質
- キープコンセプト
- 具体的な実装
- 結論
概要#
ビルダーデザインパターン(Builder Pattern)は、作成型のデザインパターンであり、複雑なオブジェクトの作成に使用されます。複雑なオブジェクトの構築プロセスを抽象化し、異なる実装のビルダーとアセンブラによって異なるオブジェクトを組み立てることができます。これにより、以前のコードを変更することなく、異なる実装のビルダーやアセンブラを簡単に追加できます。
本質#
ビルダーデザインパターン(Builder Pattern)は、オブジェクトのサブコンポーネントの構築プロセスと組み立てプロセスを分離し、構築と組み立てを切り離しています。異なるビルダーは同じ組み立て順序を持ち、同じビルダーは異なる組み立て順序で異なるオブジェクトを作成することができます。これにより、構築と組み立てが完全に切り離され、構築アルゴリズムと組み立てアルゴリズムが切り離され、より良い再利用性が実現されます。
キープコンセプト#
-
ビルダー(Builder):異なるサブコンポーネントを構築し、サブコンポーネントを返すか、複雑なオブジェクトを取得するメソッドを提供します。構築プロセスをインターフェースまたは抽象クラスとして抽象化し、具体的な異なるビルダーを拡張しやすくします。
-
アセンブラ(Director):特定のビルダーを使用して関連するサブコンポーネントを構築し、複雑な製品オブジェクトを構成するメソッドを外部に提供します。
複雑なオブジェクトを生成する必要がある場合は、特定のアセンブラを使用して必要な具体的なオブジェクトを直接取得するだけです。構築プロセスと組み立てプロセスは使用者が気にする必要はなく、それぞれ具体的なアセンブラと具体的なビルダーによって内部で完了します。もちろん、複雑なオブジェクトは多くのプロパティを持つオブジェクトと理解できます。
具体的な実装#
以下に、携帯電話の組み立てプロセスを示すためにビルダーデザインパターンの具体的な実装を示します。製品クラスは次のようになります:
/**
* 製品
*/
public class Phone {
private Screen screen;
private Camera camera;
private Cpu cpu;
// getter、setter、toString メソッドは省略
// ...
}
// サブコンポーネント
class Screen{
private String name;
// ...
}
// サブコンポーネント
class Camera{
private String name;
// ...
}
// サブコンポーネント
class Cpu{
private String name;
// ...
}
抽象ビルダー:
/**
* ビルダー
*/
public interface PhoneBuilder {
Screen builderScreen();
Camera builderCamera();
Cpu builderCpu();
}
具体的なビルダー:
/**
* 具体的なビルダー
*/
public class MiPhoneBuilder implements PhoneBuilder{
@Override
public Screen builderScreen() {
System.out.println("スクリーンを構築しています...");
return new Screen("Mi-screen");
}
@Override
public Camera builderCamera() {
System.out.println("カメラを構築しています...");
return new Camera("Mi-camera");
}
@Override
public Cpu builderCpu() {
System.out.println("CPUを構築しています...");
return new Cpu("Mi-cpu");
}
}
抽象アセンブラ:
/**
* 抽象アセンブラ
*/
public interface PhoneDirector {
Phone directPhone();
}
具体アセンブラ:
/**
* 具体アセンブラ
*/
public class MiPhoneDirector implements PhoneDirector{
private PhoneBuilder builder;
public MiPhoneDirector(PhoneBuilder builder) {
this.builder = builder;
}
@Override
public Phone directPhone() {
Phone phone = new Phone();
phone.setScreen(builder.builderScreen());
phone.setCamera(builder.builderCamera());
phone.setCpu(builder.builderCpu());
return phone;
}
}
使用者は、具体的なアセンブラを使用して最終的な製品を取得します。具体的な例は次のとおりです:
public class Client {
public static void main(String[] args) {
PhoneBuilder builder = new MiPhoneBuilder();
MiPhoneDirector director = new MiPhoneDirector(builder);
Phone phone = director.directPhone();
System.out.println(phone);
}
}
実行結果は次のようになります:
スクリーンを構築しています...
カメラを構築しています...
CPUを構築しています...
Phone [screen=Screen [name=Mi-screen], camera=Camera [name=Mi-camera], cpu=Cpu [name=Mi-cpu]]
最終的に、使用者は具体的なアセンブラである MiPhoneDirector を使用して、Mi-screen のスクリーン、Mi-camera のカメラ、Mi-cpu の CPU を持つ明確な組み立て特性を持つ携帯電話を組み立てます。
結論#
ビルダーデザインパターン(Builder Pattern)は、一般的に共通の特性を持つ複雑なオブジェクトに使用されます。オブジェクト自体と構築、組み立てプロセスが分離され、複雑なオブジェクトのプロパティが設定可能になります。もちろん、複雑なオブジェクトが内部的に複雑すぎる場合、より多くのビルダークラスを作成する必要があり、構築プロセスが煩雑になる可能性があります。私は、開発中にビルダーデザインパターンを使用してコードをより柔軟にするためのいくつかのカプセル化を行うために使用されると考えています。Picasso や Glide の API など、いくつかのプロパティを設定可能にするためにビルダーデザインパターンが使用されており、非常に便利です。