首頁 >Java >java教程 >Java設計模式中建造者模式和原型模式的介紹(程式碼範例)

Java設計模式中建造者模式和原型模式的介紹(程式碼範例)

不言
不言原創
2018-09-12 15:58:442135瀏覽

這篇文章帶給大家的內容是關於Java設計模式中建造者模式和原型模式的介紹(程式碼範例) ,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

前言

在上一篇我們學習了工廠模式,介紹了簡單工廠模式、工廠方法和抽象工廠模式。本篇則介紹設計模式中屬於創建型模式的建造者模式和原型模式。

建造者模式

簡介

建造者模式是屬於創建型模式。建造者模式使用多個簡單的物件一步一步建構成一個複雜的物件。這種類型的設計模式屬於創建型模式,它提供了一種創建物件的最佳方式。
簡單的來說就是將一個複雜的東西抽離出來,對外提供一個簡單的調用,可以在同樣的構建過程中創建不同的表示。和工廠模式很相似,不過相比而言更重視組件的組裝。

這裡用一個範例來進行說明。
我們一天吃的食物有這些,煎餅、便當、拉麵、豆漿、牛奶和果汁。分為三餐、早餐、午餐和晚餐,餐點主要包含吃的(俗稱飯)和喝的(豆漿,果汁之類的),那麼我們可以把煎餅和豆漿作為早餐,盒飯和果汁作為午餐,這樣我們可以清楚的知道要吃早餐和午餐包含什麼食物。

首先我們定義一個食物類,有兩個屬性,吃的和喝的。

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;
    }
}

定義完後,建造早餐和午餐的過程已經完成了。但這並不是建造者模式,它有個核心的Director(導演者),它用來創建複雜物件的部分,對該部分進行完整的創建或按照一定的規則進行創建。那麼這裡我們可以創建一個Director,用來創建一份餐點。至於創建的是什麼餐點,它不用知道,這一點由調用者來進行決定。

這裡我們就可以定義一個飯店,可以創建一份餐點,創建什麼餐點有顧客決定。
程式碼範例:

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. Builder:指定一個抽象的接口,規定該產品所需實現部件的創建,並不涉及具體的對象部件的創建。

  2. ConcreteBuilder:需實作Builder接口,並且針對不同的邏輯,進行不同方法的創建,最終提供該產品的實例。

  3. Director:用來建立複雜物件的部分,對該部分進行完整的建立或依照一定的規則進行建立。

  4. Product:示被建構的複雜物件。

使用場景:
適用一些基本元件不便,但是組合經常變化的時候。例如超商促銷的大禮包。

優點:

  1. 建造者獨立,容易擴充。

  2. 方便控制細節風險。

缺點

  1. 內部結構複雜,不容易理解。

  2. 產品直接需要有共同點,範圍有控制。

原型模式

原型模式(Prototype Pattern)是用來建立重複的對象,同時又能保證效能。這種類型的設計模式屬於創建型模式,它提供了一種創建物件的最佳方式。

一般來說我們在創建物件的時候是直接創建的,但是創建該物件的代價很大的時候,重複的二次創建就有些不划算,這時我們就可以使用原型模式。
打個比方,我們都寄過郵件,在節日的時候一般發送的是祝福語句,在這些祝福語句中,一般除了名字不一樣之外,大部分都是一樣的。這時我們就可以利用該模式來進行對應出創建。

這裡還是用一個的簡單的範例來說明。
小明和小紅在同一天生日,然後我們需要給他們發送郵件進行祝福,但是由於比較懶,祝福語除了名字之外都是一樣的。這時我們就可以先完成祝福語的編寫,然後複製該祝福語,最後根據不同的名稱進行發送。不過這裡就從簡了,只是簡單的列印下而已。

程式碼範例:

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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn