設計模式二(創建型)

1.原型模式

定義:通過複製現有的對象實例來創建新的對象實例。

實現:

1.實現Cloneable接口

        Cloneable接口的作用是在運行時通知虛擬機可以安全地在實現了此接口的類上使用clone方法。在java虛擬機中,只有實現了這個接口的類纔可以被拷貝,否則在運行時會拋出CloneNotSupportedException異常。
2.重寫Object類中的clone方法

       Java中,所有類的父類都是Object類,Object類中有一個clone方法,作用是返回對象的一個拷貝,但是其作用域protected類型的,一般的類無法調用,因此,原型類需要將clone方法的作用域修改爲public類型。

代碼:Mail.java

/**
 * 對於拿郵件發邀請函來說,郵件的大部分內容都是一樣的
 * 變的只是接收者的名稱和郵件地址
 */
public class Mail implements Cloneable {
    private String receiver; // 接收者地址
    private String subject;  //郵件主題(不變)
    private String content;  //郵件內容
    private String tail; //郵件結尾(不變)
    public Mail(EventTemplate et){
        this.tail = et.getEventContent();
        this.subject = et.getEventSubject();
    }
    @Override
    public Mail clone(){
        Mail mail = null;
        try {
            mail = (Mail) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return mail;
    }

    public String getReceiver() {
        return receiver;
    }

    public void setReceiver(String receiver) {
        this.receiver = receiver;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getTail() {
        return tail;
    }

    public void setTail(String tail) {
        this.tail = tail;
    }
}

EventTemplate.java

public class EventTemplate {
    private String eventContent;
    private String eventSubject;

    public EventTemplate(String eventSubject, String eventContent) {
        this.eventContent = eventContent;
        this.eventSubject = eventSubject;
    }

    public String getEventContent() {
        return eventContent;
    }

    public void setEventContent(String eventContent) {
        this.eventContent = eventContent;
    }

    public String getEventSubject() {
        return eventSubject;
    }

    public void setEventSubject(String eventSubject) {
        this.eventSubject = eventSubject;
    }
}

測試方法:

public class cloneTest {
    public static void main(String[] args) {
        //數據庫獲取被邀請人的信息
        Map<String, String> map = new HashMap<String, String>();
        map.put("張三先生", "[email protected]");
        map.put("小紅女士", "[email protected]");
        map.put("李四先生", "[email protected]");
        EventTemplate et = new EventTemplate("邀請函", "歡迎來參加我的結婚典禮。。。。");
        Mail mail = new Mail(et);
        Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, String> entry = it.next();
            Mail cloneMail = mail.clone();
            cloneMail.setContent(entry.getKey()+mail.getTail());
            cloneMail.setReceiver(entry.getValue());
            //發送郵件
            sendMail(cloneMail);
        }
    }
}

原型模式無法和單例模式一起使用(原型模式複製對象不會調用類的構造方法),一般和工廠模式一起出現。

淺拷貝是基礎類型的拷貝,深拷貝是在對象中又定義了對象時,內部的對象也要實現cloneable接口,重寫clone方法。

2.建造者模式

定義:使用多個簡單的對象,一步步構建成一個複雜的對象。例如java中的StringBuilder。

使用場景:基礎對象相對穩定,但組合多變的情況下。

代碼:

public interface Item {
    public String name();
    public float price();
    public Packing packing();
}
public interface Packing {
    public String packing();
}
public class Bottle implements Packing {
    public String packing() {
        return "瓶裝";
    }
}
public class Box implements Packing {
    public String packing() {
        return "盒裝";
    }
}
public abstract class Burger implements Item{
    @Override
    public Packing packing(){
        return new Box();
    }
}
public abstract class ChickenWing implements Item{
    @Override
    public Packing packing(){
        return new Box();
    }
}
public abstract class Drink implements Item{
    @Override
    public Packing packing(){
        return new Bottle();
    }
}
public class ChickenBurger extends Burger {
    @Override
    public String name() {
        return "雞肉漢堡";
    }

    @Override
    public float price() {
        return 18.5f;
    }
}
public class VegBurger extends Burger {
    @Override
    public String name() {
        return "蔬菜漢堡";
    }

    @Override
    public float price() {
        return 12.5f;
    }
}
public class RoastChickWing extends ChickenWing {
    @Override
    public String name() {
        return "奧爾良烤雞翅";
    }

    @Override
    public float price() {
        return 10;
    }
}
public class Coke extends Drink {
    @Override
    public String name() {
        return "可樂";
    }

    @Override
    public float price() {
        return 10;
    }
}
public class Milk extends Drink {
    @Override
    public String name() {
        return "牛奶";
    }

    @Override
    public float price() {
        return 12.5f;
    }
}
public class Meal {
    private List<Item> items = new ArrayList<Item>();

    public void addItem(Item item){
        items.add(item);
    }

    public float getCost(){
        float cost = 0.0f;
        for (Item item : items) {
            cost += item.price();
        }
        return cost;
    }

    public void showItems(){
        for (Item item : items) {
            System.out.print("Item : "+item.name());
            System.out.print(", Packing : "+item.packing().packing());
            System.out.println(", Price : "+item.price());
        }
    }
}
public class MealBuilder {
    public Meal meal1() {
        Meal meal = new Meal();
        meal.addItem(new ChickenBurger());
        meal.addItem(new RoastChickWing());
        meal.addItem(new Coke());
        return meal;
    }

    public Meal meal2() {
        Meal meal = new Meal();
        meal.addItem(new VegBurger());
        meal.addItem(new Milk());
        return meal;
    }
}

測試:

public class BuilderTest {
    public static void main(String[] args){
        MealBuilder mealBuilder = new MealBuilder();
        Meal meal1 = mealBuilder.meal1();
        System.out.println("套餐一");
        meal1.showItems();
        System.out.println("Total Cost: " +meal1.getCost());
        Meal meal2 = mealBuilder.meal2();
        System.out.println("套餐二");
        meal2.showItems();
        System.out.println("Total Cost: " +meal2.getCost());
    }
}

結果:


參考http://www.runoob.com/design-pattern/builder-pattern.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章