Java デザイン パターンのビルダー パターンとプロトタイプ パターンの概要 (コード例)

不言
リリース: 2018-09-12 15:58:44
オリジナル
2103 人が閲覧しました

この記事では、Java デザイン パターンのビルダー パターンとプロトタイプ パターンの紹介 (コード例) を紹介します。必要な方は参考にしていただければ幸いです。

はじめに

前回の記事では、ファクトリ パターンについて学び、単純なファクトリ パターン、ファクトリ メソッド、および抽象ファクトリ パターンを紹介しました。この記事では、デザインパターンのクリエイティブパターンであるビルダーパターンとプロトタイプパターンについて紹介します。

ビルダーモード

はじめに

ビルダーモードはクリエイティブモードです。ビルダー パターンは、複数の単純なオブジェクトを使用して、複雑なオブジェクトを段階的に構築します。このタイプのデザイン パターンは創造的なパターンであり、オブジェクトを作成するための最適な方法を提供します。
簡単に言うと、複雑なものを抽出し、外部の世界に単純な呼び出しを提供することで、同じ構築プロセスで異なる表現を作成できます。これはファクトリー モードとよく似ていますが、コンポーネントの組み立てにより注意が払われます。

これを説明する例を示します。
私たちが毎日食べる食べ物には、パンケーキ、お弁当、ラーメン、豆乳、牛乳、ジュースなどがあります。朝食、昼食、夕食の3食に分かれており、食事は主に食べ物(通称ご飯)と飲み物(豆乳、ジュースなど)で、朝食としてパンケーキや豆乳を食べたり、お弁当を食べたりすることができます。昼食としてジュースを食べるので、朝食と昼食に何を食べるべきかを正確に知ることができます。

まず、食べ物と飲み物という 2 つの属性を持つ食品カテゴリを定義します。

class Meal{
    private String food;
    private String drinks;
    
    public String getFood() {
        return food;
    }
    public void setFood(String food) {
        this.food = food;
    }
    
    public String getDrinks() {
        return drinks;
    }
    public void setDrinks(String drinks) {
        this.drinks = drinks;
    }
}
ログイン後にコピー

私たちが食品を定義するとき、私たちは食品の標準インターフェースを定義しています。実際、それは食べることと飲むことを意味します。

interface IBuilderFood{
    void buildFood();
    void buildDrinks();
    Meal createMeal();
}
ログイン後にコピー

フード インターフェースは、食べるコンポーネントと飲むコンポーネントを定義し、createMeal() メソッドを通じて必要な食べ物を返します。
これで、朝食と昼食を定義できます。
コード例:

class Breakfast implements IBuilderFood{
    Meal meal;

    public Breakfast(){
        meal=new Meal();
    }
    
    @Override
    public void buildFood() {
        meal.setFood("煎饼");
    }

    @Override
    public void buildDrinks() {
        meal.setDrinks("豆浆");   
    }
    
    @Override
    public Meal createMeal() {
        return meal;
    }
}

class Lunch implements IBuilderFood{
    Meal meal;

    public Lunch(){
        meal=new Meal();
    }
    
    @Override
    public void buildFood() {
        meal.setFood("盒饭");
    }

    @Override
    public void buildDrinks() {
        meal.setDrinks("果汁");   
    }
    
    @Override
    public Meal createMeal() {
        return meal;
    }
}
ログイン後にコピー

定義後、朝食と昼食を構築するプロセスは完了です。ただし、これはビルダー モードではありません。コア ディレクターは、複雑なオブジェクトの一部を作成したり、パーツを完全に作成したり、特定のルールに従って作成したりするために使用されます。ここで、食事を作成するためのディレクターを作成できます。どのような食事が作成されるかについては、知る必要はありません。これは呼び出し元によって決定されます。

ここでレストランを定義し、食事を作成するのは顧客が決定します。
コード例:

class FoodStore{
    public Meal createBreakfast(IBuilderFood bf){
        bf.buildDrinks();
        bf.buildFood();
        return bf.createMeal();
    }
}
ログイン後にコピー

この Director を作成したら、通話テストを実行してみましょう。

コード例:

public class BuilderTest {

    public static void main(String[] args) {
        FoodStore foodStore=new FoodStore();
        Meal meal=foodStore.createBreakfast(new Breakfast());
        Meal meal2=foodStore.createBreakfast(new Lunch());
        System.out.println("小明早上吃的是:"+meal.getFood()+",喝的饮料是:"+meal.getDrinks());
        System.out.println("小明中午吃的是:"+meal2.getFood()+",喝的饮料是:"+meal2.getDrinks()); 
    }

}
ログイン後にコピー

出力結果:

小明早上吃的是:煎饼,喝的饮料是:豆浆
小明中午吃的是:盒饭,喝的饮料是:果汁
ログイン後にコピー

は、ビルダーモードの動作原理を簡単に紹介します。これは次の 4 つの点に要約できます:

  1. ビルダー: 抽象インターフェイスを指定し、この製品に必要なコンポーネントの作成には、特定のオブジェクト コンポーネントの作成は含まれません。

  2. ConcreteBuilder: Builder インターフェイスを実装し、さまざまなロジックにさまざまなメソッドを作成し、最終的にプロダクトのインスタンスを提供する必要があります。

  3. ディレクター: 複雑なオブジェクトの一部を作成するために使用され、この部分を完全に、または特定のルールに従って作成します。

  4. Product: 構築された複合オブジェクトを示します。

使用シナリオ:
いくつかの基本コンポーネントは不便だが、組み合わせが頻繁に変更される場合に適用されます。たとえば、スーパーマーケットの販促用ギフトパッケージなどです。

利点:

  1. ビルダーに依存せず、拡張が簡単です。

  2. 細かいリスクをコントロールしやすい。

デメリット

  1. 内部構造が複雑でわかりにくい。

  2. 製品には直接共通点が必要であり、範囲を制御する必要があります。

プロトタイプパターン

プロトタイプパターンは、パフォーマンスを確保しながら繰り返しオブジェクトを作成するために使用されます。このタイプのデザイン パターンは創造的なパターンであり、オブジェクトを作成するための最適な方法を提供します。

一般的に、オブジェクトを作成する場合は直接作成しますが、オブジェクトの作成コストが高い場合、二次作成を繰り返すのは費用対効果が高くありません。この場合は、プロトタイプ モードを使用できます。
例えば、私たちは祭りの際に、名前を除いてほとんど同じ祝福を送ります。現時点では、このモードを使用して適切に作成できます。

これを説明するための簡単な例を示します。
シャオミンとシャオホンは同じ日に誕生日なので、お祝いのメールを送る必要がありますが、私たちは怠け者なので、祝福の言葉は名前を除いて同じです。現時点では、最初に祝福の書き込みを完了し、次に祝福を複製し、最後に異なる名前に従って送信できます。ただし、ここでは簡単にしておきますので、印刷してください。

コード例:

public class PrototypeTest {

    public static void main(String[] args) {
        Mail mail=new Mail();
        mail.setMsg("生日快乐!");
        Mail mail2=(Mail) mail.clone();
        mail.setName("小明");
        mail2.setName("小红");
        System.out.println(mail.toString());
        System.out.println(mail2.toString());
    }
}

 class Mail implements Cloneable {
    private String name;
    private String msg;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return clone;
    }

    @Override
    public String toString() {
        return name + ":" + msg ;
    }
    
}
ログイン後にコピー

出力結果:

小明:生日快乐!
小红:生日快乐!
ログイン後にコピー

看完原型模式的创建,是不是感觉就是和Java中克隆即为类似呢?
实际上它的核心也就是克隆。
克隆有两种,浅克隆和深克隆,本文主要介绍的是浅克隆。
浅克隆:

在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。
实现Cloneable接口并重写Object类中的clone()方法;

深克隆:

在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。

简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。
实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

使用场景:

  1. 类初始化的时候需要消耗大量资源的时候;

  2. 获取数据库连接繁琐的时候;

  3. 一个对象,有很多个修改者的时候;

优点:
1.可以提升性能;

缺点:
1.因为必须实现Cloneable 接口,所以用起来可能不太方便。

相关推荐:

Java设计模式中工厂模式的介绍(代码示例)

Java设计模式是什么?Java设计模式中单例模式的介绍

以上がJava デザイン パターンのビルダー パターンとプロトタイプ パターンの概要 (コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート