検索
ホームページJava&#&チュートリアルJava デザイン パターンのビルダー パターンとプロトタイプ パターンの概要 (コード例)

この記事では、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 サイトの他の関連記事を参照してください。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
带你搞懂Java结构化数据处理开源库SPL带你搞懂Java结构化数据处理开源库SPLMay 24, 2022 pm 01:34 PM

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于结构化数据处理开源库SPL的相关问题,下面就一起来看一下java下理想的结构化数据处理类库,希望对大家有帮助。

Java集合框架之PriorityQueue优先级队列Java集合框架之PriorityQueue优先级队列Jun 09, 2022 am 11:47 AM

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于PriorityQueue优先级队列的相关知识,Java集合框架中提供了PriorityQueue和PriorityBlockingQueue两种类型的优先级队列,PriorityQueue是线程不安全的,PriorityBlockingQueue是线程安全的,下面一起来看一下,希望对大家有帮助。

完全掌握Java锁(图文解析)完全掌握Java锁(图文解析)Jun 14, 2022 am 11:47 AM

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于java锁的相关问题,包括了独占锁、悲观锁、乐观锁、共享锁等等内容,下面一起来看一下,希望对大家有帮助。

一起聊聊Java多线程之线程安全问题一起聊聊Java多线程之线程安全问题Apr 21, 2022 pm 06:17 PM

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于多线程的相关问题,包括了线程安装、线程加锁与线程不安全的原因、线程安全的标准类等等内容,希望对大家有帮助。

Java基础归纳之枚举Java基础归纳之枚举May 26, 2022 am 11:50 AM

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于枚举的相关问题,包括了枚举的基本操作、集合类对枚举的支持等等内容,下面一起来看一下,希望对大家有帮助。

详细解析Java的this和super关键字详细解析Java的this和super关键字Apr 30, 2022 am 09:00 AM

本篇文章给大家带来了关于Java的相关知识,其中主要介绍了关于关键字中this和super的相关问题,以及他们的一些区别,下面一起来看一下,希望对大家有帮助。

Java数据结构之AVL树详解Java数据结构之AVL树详解Jun 01, 2022 am 11:39 AM

本篇文章给大家带来了关于java的相关知识,其中主要介绍了关于平衡二叉树(AVL树)的相关知识,AVL树本质上是带了平衡功能的二叉查找树,下面一起来看一下,希望对大家有帮助。

java中封装是什么java中封装是什么May 16, 2019 pm 06:08 PM

封装是一种信息隐藏技术,是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法;封装可以被认为是一个保护屏障,防止指定类的代码和数据被外部类定义的代码随机访问。封装可以通过关键字private,protected和public实现。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

MantisBT

MantisBT

Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。

SublimeText3 Linux 新バージョン

SublimeText3 Linux 新バージョン

SublimeText3 Linux 最新バージョン

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。