1. 程式人生 > >常見設計模式總結(一)單例&觀察者&裝飾者

常見設計模式總結(一)單例&觀察者&裝飾者

目錄

單例模式

簡單點說,就是一個應用程式中,某個類的例項物件只有一個,你沒有辦法去new,因為構造器是被private修飾的,一般通過getInstance()的方法來獲取它們的例項。getInstance()的返回值是一個物件的引用,並不是一個新的例項,所以不要錯誤的理解成多個物件。 例子:

public class Singleton {
	private static Singleton singleton;
	private Singleton() {}
	public static Singleton getInstance() {
		if (singleton == null) {
			singleton = new Singleton();
		}
		return singleton;
	}
}

單例模式的兩種寫法:

懶漢: 是你真正用到的時候才去建這個單例物件 餓漢: 是不管你用的用不上,一開始就建立這個單例物件

// 懶漢式
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

// 餓漢式
public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    	return instance;  
    }  
} 

觀察者模式

物件間一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新。 舉個通俗的栗子:

    有三個人,小美,老王和老李。小美很漂亮,很風騷,老王和老李是兩個中年男屌絲,時刻關注著小美的一舉一動。
    有一天,小美說了一句:我老公今天不在家,一個人好無聊啊~~~,這句話被老王和老李聽到了,結果樂壞了,
蹭蹭蹭,沒一會兒,老王就衝到小美家門口了,於是進門了……~ 
    在這裡,小美是被觀察者,老王和老李是觀察者,被觀察者發出一條資訊,然後觀察者們進行相應的處理。

程式碼如下:

public interface Person {
    //老王和老李通過這個介面可以接收到小美髮過來的訊息
    void getMessage(String s);
}

這個介面相當於老王和老李的電話號碼,小美髮送通知的時候就會呼叫getMessage這個介面。

// 這是老王,老李的類似,都實現了Person介面(接收小美的訊息)
public class LaoWang implements Person {
    private String name = "老王";
    public LaoWang() {}
    @Override
    public void getMessage(String s) {
        System.out.println(name + "接到了小美打過來的電話,電話內容是:" + s);
    }
}

// 這是小美
public class XiaoMei {
     List<Person> list = new ArrayList<Person>();
     public XiaoMei(){
     }
     public void addPerson(Person person){
         list.add(person);
     }
     //遍歷list,把自己的通知傳送給所有暗戀自己的人
     public void notifyPerson() {
         for(Person person:list){
             person.getMessage("今天家裡就我一個人,你們過來吧,先到先得!");
         }
     }
}

我們寫一個測試類來看一下結果

public class Test {
    public static void main(String[] args) {
        XiaoMei xiao_mei = new XiaoMei();
        LaoWang lao_wang = new LaoWang();
        LaoLi lao_li = new LaoLi();
        //老王和老李在小美那裡都註冊了一下
        xiao_mei.addPerson(lao_wang);
        xiao_mei.addPerson(lao_li);
        //小美向老王和老李傳送通知
        xiao_mei.notifyPerson();
    }
}

執行結果:

老王接到了小美打過來的電話,電話內容是:今天家裡就我一個人,你們過來吧,先到先得!
老李接到了小美打過來的電話,電話內容是:今天家裡就我一個人,你們過來吧,先到先得!

裝飾者模式

對已有的業務邏輯進一步的封裝,使其增加額外的功能。 如Java中的IO流就使用了裝飾者模式,使用者在使用的時候,可以任意組裝,達到自己想要的效果。 舉個栗子,我想吃三明治,首先我需要一根大大的香腸,我喜歡吃奶油,在香腸上面加一點奶油,再放一點蔬菜,最後再用兩片面包夾一下,營養又健康。

那我們應該怎麼來寫程式碼呢? 首先,我們需要寫一個Food類,讓其他所有食物都來繼承這個類 食物類:

public class Food {
    private String foodName;
    public Food(){}
    public Food(String foodName){
        this.foodName = foodName;
    }
    public String make(){
        return foodName;
    }
}

麵包類:

public class Bread extends Food {
    private Food basicFood;
    public Bread(Food basicFood) {
        this.basicFood = basicFood;
    }
    public String make() {
        return basicFood.make() + "+麵包";
    }
}

奶油類:

public class Cream extends Food {
    private Food basicFood;
    public Cream(Food basicFood) {
        this.basicFood = basicFood;
    }
    public String make() {
        return basicFood.make() + "+奶油";
    }
}

這幾個類都是差不多的,構造方法傳入一個Food型別的引數,然後在make方法中加入一些自己的邏輯

public class Test {
    public static void main(String[] args) {
        Food food = new Bread(new Cream(new Food("5元肉夾饃")));
        System.out.println(food.make());
    }
}

執行結果:

5元肉夾饃+奶油+麵包