Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 軟件設計模式之觀察者模式、Builder模式、單例模式、簡單工廠模式

軟件設計模式之觀察者模式、Builder模式、單例模式、簡單工廠模式

編輯:關於Android編程

工作內容:

1.觀察者模式

2.Builder模式

3.單例模式

4.簡單工廠模式

學習分享:

一、觀察者模式【代碼參考例1】

在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統。[觀察者和被觀察者之間存在“觀察”的邏輯關聯,當被觀察者發生改變的時候,觀察者就會觀察到這樣的變化,並且做出相應的響應。]

觀察者:(Observer)將自己注冊到被觀察對象(Subject)中,被觀察對象將觀察者存放在一個容器(Container)裡。

被觀察:被觀察對象發生了某種變化(如圖中的SomeChange),從容器中得到所有注冊過的觀察者,將變化通知觀察者。

二、Builder模式【代碼參考例2】

(1) 意圖:將一個“復雜對象的構建算法”與它的“部件及組裝方式”分離,使得構件算法和組裝方式可以獨立應對變化;復用同樣的構建算法可以創建不同的表示,不同的構建過程可以復用相同的部件組裝方式。
(2) 適用性:
當同時滿足以下情況的時候可以使用Builder模式
a. 當創建復雜對象的算法應該獨立於該對象的組成部分以及他們的裝配方式;
b. 當構造過程必須允許構造的對象有不同的表示;

(3)Builder模式的核心是“聚合”

三、單例模式【代碼參考例1中的Subject】

在它的核心結構中只包含一個被稱為單例的特殊類。通過單例模式可以保證系統中一個類只有一個實例。

“保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。”

單例模式的要點有三個;一是某個類只能有一個實例;二是它必須自行創建這個實例;三是它必須自行向整個系統提供這個實例。

具體實現角度來說,就是以下三點:一是單例模式的類只提供私有的構造函數,二是類定義中含有一個該類的靜態私有對象,三是該類提供了一個靜態的公有的函數用於創建或獲取它本身的靜態私有對象。

優點
一、實例控制
單例模式會阻止其他對象實例化其自己的單例對象的副本,從而確保所有對象都訪問唯一實例。
二、靈活性
因為類控制了實例化過程,所以類可以靈活更改實例化過程。
缺點
一、開銷
雖然數量很少,但如果每次對象請求引用時都要檢查是否存在類的實例,將仍然需要一些開銷。可以通過使用靜態初始化解決此問題。
二、可能的開發混淆
使用單例對象(尤其在類庫中定義的對象)時,開發人員必須記住自己不能使用new關鍵字實例化對象。因為可能無法訪問庫源代碼,因此應用程序開發人員可能會意外發現自己無法直接實例化此類。
三、對象生存期
不能解決刪除單個對象的問題。在提供內存管理的語言中(例如基於.NET Framework的語言),只有單例類能夠導致實例被取消分配,因為它包含對該實例的私有引用。在某些語言中(如 C++),其他類可以刪除對象實例,但這樣會導致單例類中出現懸浮引用。。

注意;在Android中的多線程中調用此方法應該在getInstance方法中用用synchronized來鎖定該類(這裡是Subject.class)

四、工廠模式【代碼參考例3】

工廠模式在《Java與模式》中分為三類:
1)簡單工廠模式(Simple Factory):不利於產生系列產品;
2)工廠方法模式(Factory Method):又稱為多形性工廠;
3)抽象工廠模式(Abstract Factory):又稱為工具箱,產生產品族,但不利於產生新的產品;
一、簡單工廠模式
簡單工廠模式又稱靜態工廠方法模式。重命名上就可以看出這個模式一定很簡單。它存在的目的很簡單:定義一個用於創建對象的接口。在簡單工廠模式中,一個工廠類處於對產品類實例化調用的中心位置上,它決定那一個產品類應當被實例化, 如同一個交通警察站在來往的車輛流中,決定放行那一個方向的車輛向那一個方向流動一樣。
先來看看它的組成:
1) 工廠類角色:這是本模式的核心,含有一定的商業邏輯和判斷邏輯。在java中它往往由一個具體類實現。
2) 抽象產品角色:它一般是具體產品繼承的父類或者實現的接口。在java中由接口或者抽象類來實現。
3) 具體產品角色:工廠類所創建的對象就是此角色的實例。在java中由一個具體類實現。
二、工廠方法模式
工廠方法模式是簡單工廠模式的進一步抽象化和推廣,工廠方法模式裡不再只由一個工廠類決定那一個產品類應當被實例化,這個決定被交給抽象工廠的子類去做。
  來看下它的組成:
1)抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。在java中它由抽象類或者接口來實現。
2)具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。
3)抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在java中一般有抽象類或者接口來實現。
4)具體產品角色:具體工廠角色所創建的對象就是此角色的實例。在java中由具體的類來實現。
工廠方法模式使用繼承自抽象工廠角色的多個子類來代替簡單工廠模式中的“上帝類”。正如上面所說,這樣便分擔了對象承受的壓力;而且這樣使得結構變得靈活 起來——當有新的產品(即暴發戶的汽車)產生時,只要按照抽象產品角色、抽象工廠角色提供的合同來生成,那麼就可以被客戶使用,而不必去修改任何已有的代 碼。可以看出工廠角色的結構也是符合開閉原則的!

 

//抽象產品角色
public interface Moveable {
    void run();
}
//具體產品角色
public class Plane implements Moveable {
    @Override
    public void run() {
        System.out.println("plane....");
    }
}

public class Broom implements Moveable {
    @Override
    public void run() {
        System.out.println("broom.....");
    }
}

//抽象工廠
public abstract class VehicleFactory {
    abstract Moveable create();
}
//具體工廠
public class PlaneFactory extends VehicleFactory{
    public Moveable create() {
        return new Plane();
    }
}
public class BroomFactory extends VehicleFactory{
    public Moveable create() {
        return new Broom();
    }
}
//測試類
public class Test {
    public static void main(String[] args) {
        VehicleFactory factory = new BroomFactory();
        Moveable m = factory.create();
        m.run();
    }
}
可以看出工廠方法的加入,使得對象的數量成倍增長。當產品種類非常多時,會出現大量的與之對應的工廠對象,這不是我們所希望的。因為如果不能避免這種情 況,可以考慮使用簡單工廠模式與工廠方法模式相結合的方式來減少工廠類:即對於產品樹上類似的種類(一般是樹的葉子中互為兄弟的)使用簡單工廠模式來實 現。
簡單工廠和工廠方法模式的比較
工廠方法模式和簡單工廠模式在定義上的不同是很明顯的。工廠方法模式的核心是一個抽象工廠類,而不像簡單工廠模式, 把核心放在一個實類上。工廠方法模式可以允許很多實的工廠類從抽象工廠類繼承下來, 從而可以在實際上成為多個簡單工廠模式的綜合,從而推廣了簡單工廠模式。
反過來講,簡單工廠模式是由工廠方法模式退化而來。設想如果我們非常確定一個系統只需要一個實的工廠類, 那麼就不妨把抽象工廠類合並到實的工廠類中去。而這樣一來,我們就退化到簡單工廠模式了。
三、抽象工廠模式
在抽象工廠模式中,抽象產品 (AbstractProduct) 可能是一個或多個,從而構成一個或多個產品族(Product Family)。 在只有一個產品族的情況下,抽象工廠模式實際上退化到工廠方法模式。

 

 

//抽象工廠類
public abstract class AbstractFactory {
    public abstract Vehicle createVehicle();
    public abstract Weapon createWeapon();
    public abstract Food createFood();
}
//具體工廠類,其中Food,Vehicle,Weapon是抽象類,
public class DefaultFactory extends AbstractFactory{
    @Override
    public Food createFood() {
        return new Apple();
    }
    @Override
    public Vehicle createVehicle() {
        return new Car();
    }
    @Override
    public Weapon createWeapon() {
        return new AK47();
    }
}
//測試類
public class Test {
    public static void main(String[] args) {
        AbstractFactory f = new DefaultFactory();
        Vehicle v = f.createVehicle();
        v.run();
        Weapon w = f.createWeapon();
        w.shoot();
        Food a = f.createFood();
        a.printName();
    }
}

例1:觀察者模式+單列模式

 

//觀察者接口【發現被觀察的對象的狀態或者數據發生改變時要做的事】
public interface CallBackObserver {
    void afterChangeDo();//被觀察的數據/狀態改變後執行
}
class Observer_1 implements CallBackObserver{
    private String observerName="";
    public String getObserverName() {
        return observerName;
    }
    public void setObserverName(String observerName) {
        this.observerName = observerName;
    }
    //構造函數,傳入觀察者名稱,便於區分
    public Observer_1(String observerName) {
        super();
        this.observerName = observerName;
    }
    @Override
    public void afterChangeDo() {
        System.out.println(observerName+"執行afterChangeDo");
    }
}

//被觀察者(類)的父類
public abstract class SubjectFather {
    public abstract void bindObserver(Observer_1 observer);//綁定
    public abstract void disBindObserver(Observer_1 observer);        //解綁
    public abstract void notifyAllObserver();        //通知所有觀察者
}

//被觀察者(實體類):
class Subject  extends SubjectFather{
    private List list;
    /**
     * 這裡使用了單例模式(懶漢式)來構造一個Subject對象
     * 單例模式:私有化構造函數,常用一個public static Subject getInstance()方法來獲得Subject的對象
     */
    private static Subject subject=null;
    public static Subject getInstance(){
        if(subject == null){
            subject = new Subject();
        }
        return subject;
    }
    // 私有化構造函數【不允許在外部通過new來構造對象】
    private Subject() {
        list = new ArrayList<>();
    }
    @Override
    public void bindObserver(Observer_1 observer) {
        list.add(observer);
        System.out.println("綁定——"+observer.getObserverName());
    }

    @Override
    public void disBindObserver(Observer_1 observer) {
        list.remove(observer);
        System.out.println("解綁——"+observer.getObserverName());
    }

    public void dataChange(int i) {
        System.out.println("數據發生第"+i+"次改變");
        notifyAllObserver();
    }
    @Override
    public void notifyAllObserver() {
        for (Observer_1 observer_1 : list) {
            observer_1.afterChangeDo();
        }
    }
}

//觀察者模式的演示類
public class ObserverDemo {
    public static void main(String[] args) {
        Subject subject = Subject.getInstance();
        Observer_1 observer_1 = new Observer_1("觀察者1");
        Observer_1 observer_2 = new Observer_1("觀察者2");
        Observer_1 observer_3 = new Observer_1("觀察者3");
        // 綁定
        subject.bindObserver(observer_1);
        subject.bindObserver(observer_2);
        subject.bindObserver(observer_3);

        // 數據改變
        subject.dataChange(1);
        subject.dataChange(2);
        subject.dataChange(3);

        // 解綁
        subject.disBindObserver(observer_1);
        subject.disBindObserver(observer_2);
        subject.disBindObserver(observer_3);
    }
}

 

運行結果:

綁定——觀察者1
綁定——觀察者2
綁定——觀察者3
數據發生第1次改變
觀察者1執行afterChangeDo
觀察者2執行afterChangeDo
觀察者3執行afterChangeDo
數據發生第2次改變
觀察者1執行afterChangeDo
觀察者2執行afterChangeDo
觀察者3執行afterChangeDo
數據發生第3次改變
觀察者1執行afterChangeDo
觀察者2執行afterChangeDo
觀察者3執行afterChangeDo
解綁——觀察者1
解綁——觀察者2
解綁——觀察者3

例2:Builder簡單寫法[寫法有很多種,可以自己多去嘗試]

 

public class Apple {
	private String name;	//名稱
	private double price;	//價格
	private int color;			//顏色
	private int memory;	//存儲空間大小
	private int mode;		//聯網方式
	//構造函數私有化,防止直接生成對象
	private Apple(String name, double price, int color, int memory, int mode) {
		super();
		this.name = name;
		this.price = price;
		this.color = color;
		this.memory = memory;
		this.mode = mode;
	}
	//測試用
	@Override
	public String toString() {
		return "Apple [name=" + name + ", price=" + price + ", color=" + color + ", memory=" + memory + ", mode=" + mode
				+ "]";
	}
	static class Builder{
		private String name;	//名稱
		private double price;	//價格
		private int color;			//顏色
		private int memory;	//存儲空間大小
		private int mode;
		public Apple build(){
			//返回Apple的對象
			//可以在這裡設置默認值【當傳入值為空或者沒有set時的默認值】
			return new Apple(name,price,color,memory,mode);
		}
		//方法返回是Builder,就可以一直使用.方法名,來調用Builder中的方法
		//可以在方法中約束傳入的值得“范圍”
		public Builder setName(String name) {
			this.name = name;
			return this;
		}
		public Builder setPrice(double price) {
			this.price = price;
			return this;
		}
		public Builder setColor(int color) {
			this.color = color;
			return this;
		}
		public Builder setMemory(int memory) {
			this.memory = memory;
			return this;
		}
		public Builder setMode(int mode) {
			this.mode = mode;
			return this;
		}		
	}
}
//測試Builder的Demo
public class TespBuilder {
	public static void main(String[] args) {
		Apple apple = new Apple.Builder()
				.setColor(0)
				.setMemory(64)
				.setMode(1)
				.setName("iphone5s")
//				.setPrice(2600)
				.build();
		System.out.println(apple);
	}
}
運行結果:

 

Apple [name=iphone5s, price=0.0, color=0, memory=64, mode=1]
 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved