1. 程式人生 > >設計模式(一) 觀察者模式、裝飾模式、工廠模式

設計模式(一) 觀察者模式、裝飾模式、工廠模式

               ---------------------- ASP.Net+Android+IOS開發.Net培訓、期待與您交流! ----------------------

1.觀察者模式

觀察者模式  定義了物件之間的一對多依賴,這樣一來,當一個物件改變狀態時,它的所有依賴者都會收到通知並自動更新。

     

先我們需要一個 主題介面,物件可以使用該介面註冊為觀察者或者將自己從觀察者中刪除:

Subject介面:

/*
 * 主題介面,物件使用此介面註冊為觀察者或者將自己從觀察著中刪除
 */
public interface Subject {	
    /*
     *  註冊觀察者
     */
	public void registObserver(Observer observer);
	/*
	 *  刪除觀察者
	 */
	public void removeObserver(Observer observer);
	/*
	 *  提醒觀察者更新資料
	 */
	public void notifyObserver();
}

Observer介面:
public interface Observer {	
	/*
	 * 更新資料
	 */
	public void update(String team,String score);
}
Subject實現類MatchData:
public class MatchData implements Subject{
	
	public void registObserver(Observer observer) {
		this.observers.add(observer);
		
	}
	public void removeObserver(Observer observer) {
		int i = observers.indexOf(observer);
		if(i >= 0){
			observers.remove(i);
		}
	}
	public void notifyObserver() {
		for(int i=0; i<observers.size(); i++){
			Observer observer = observers.get(i);
			observer.update(team, score);
		}
	}
	
	public void setMatchData(String team,String score){
		this.team = team;
		this.score = score;
		notifyObserver();
	}
	
	private String team;
	private String score;
	private List<Observer> observers = new ArrayList<Observer>();
}

Observer實現類TVObserver、WebsitObserver:
public class TVObserver implements Observer{

	public TVObserver(Subject subject){
		this.subject = subject;
		this.subject.registObserver(this);
	}
	
	public void update(String team, String score) {
		this.team = team;
		this.score = score;
		this.display();
	}
	
	public void display(){
		System.out.println("現在是TV直播,正在播放的比賽是 : " + team + " 現在的比分是:" + score);
	}
	
	private Subject subject;
	private String team;
	private String score;

}

public class WebsitObserver implements Observer{
	
	public WebsitObserver(Subject subject){
		this.subject = subject;
		this.subject.registObserver(this);
	}

	public void update(String team, String score) {
		this.team = team;
		this.score = score;
		this.display();
	}
	
	public void display(){
		System.out.println("這裡是比賽直播網站,比賽的最新賽況 : " + team + " 比分 : " + score);
	}
	
	private String team;
	private String score;
	private Subject subject;

}

使用程式碼:
public static void main(String[] args){
		
		MatchData matchData = new MatchData();
		Observer websit = new WebsitObserver(matchData);
		Observer tvObserver = new TVObserver(matchData);
        
		matchData.setMatchData("西班牙VS巴西", "1:2");
		matchData.setMatchData("美國VS英國", "0:1");
		matchData.setMatchData("西班牙VS葡萄牙", "1:1");
		
	}


2.裝飾模式

  裝飾模式:動態的將責任附加到物件上,若要擴充套件功能,裝飾著提供了比繼承更有彈性的替代方案。

  

具體的用法用程式碼演示:

定義一個抽象的Food抽象類

public abstract class Food {

	public String getDescription() {
		return description;
	}

	protected String description = "Just Rice";
}
定義一個繼承Food的類Rice和Black_kerneled_rice
public class Rice extends Food{
	
	public Rice(){
		this.description = "Rice";
	}

}
public class Black_kerneled_rice extends Food{
	public Black_kerneled_rice(){
		this.description = "black kerneled rice";
	}
}
裝飾者:
public abstract class Comdiment extends Food{
	
	public abstract String getDescription();

}
繼承自裝飾著的類:
public class Salt extends Comdiment{

	public Salt(Food food){
		this.food = food;
	}
	
	public String getDescription() {
		return this.food.getDescription() + " ,salt";
	}
	
	private Food food;

}

public class Soy_sauce extends Comdiment{

	public Soy_sauce(Food food){
		this.food = food;
	}
	
	public String getDescription() {
		return this.food.getDescription() + " ,soy sauce";
	}
	
	private Food food;

}

public class Chicken_essence extends Comdiment{

	public Chicken_essence(Food food){
		this.food = food;
	}
	
	public String getDescription() {
		return this.food.getDescription() + " ,chicken essence";
	}
	
	private Food food;

}
使用程式碼:
public static void main(String[] args){
		/*
		 *  白米油炒飯 加醬油、鹽、雞精
		 */
		Food food = new Rice();
		food = new Salt(food);
		food = new Soy_sauce(food);
		food = new Chicken_essence(food);
		System.out.println(food.getDescription());
		/*
		 *  黑米炒飯 加鹽、雙份雞精
		 */
		food = new Black_kerneled_rice();
		food = new Salt(food);
		food = new Chicken_essence(food);
		food = new Chicken_essence(food);
		System.out.println(food.getDescription());
		
	}

3.工廠方法模式

工廠方法模式:定義一個建立物件的介面,但由子類決定要是梨花的類是哪一個。工廠方法讓例項化推遲到子類。


具體用一個蛋糕店來演示:

抽象類Cake:

public abstract class Cake {

	public String getName() {
		return this.name;
	}

	public abstract void prepare(); // 準備工作
 
	public abstract void bake(); // 烘烤
	
	public abstract void decorate(); // 新增飾品 
	 
	public abstract void box(); // 裝箱

	protected String name;
}
生產蛋糕的工廠:
public abstract class CakeFactory {

	public Cake createCake(String name) {
		this.cake = this.makeCake(name);
		cake.prepare();
		cake.bake();
		cake.decorate();
		cake.box();
		return cake;
	}

	public abstract Cake makeCake(String name);

	private Cake cake;
}

雞蛋蛋糕、水果蛋糕:
public class EggCake extends Cake {

	public EggCake(String name) {
		this.name = name;
	}

	public void prepare() {
		System.out.println("準備麵粉,奶油,雞蛋,甜精");
		System.out.println("將麵粉和雞蛋、甜精一起攪拌");
		System.out.println("攪拌後做成蛋糕的形狀");
	}

	public void bake() {
		System.out.println("將做好的蛋糕原型放入烤箱烘烤,烤好後就出爐了");
	}

	public void decorate() {
		System.out.println("將烤好後的蛋糕新增奶油、巧克力");
	}

	public void box() {
		System.out.println("將加好奶油的蛋糕裝入蛋糕盒");
	}

	public String getName() {
		return this.name;
	}

}

public class FruitCake extends Cake {

	public FruitCake(String name) {
		this.name = name;
	}

	public void prepare() {
		System.out.println("準備麵粉,奶油,甜精");
		System.out.println("將麵粉和甜精一起攪拌");
		System.out.println("攪拌後做成蛋糕的形狀");
	}

	public void bake() {
		System.out.println("將做好的蛋糕原型放入烤箱烘烤,烤好後就出爐了");
	}

	public void decorate() {
		System.out.println("將烤好後的蛋糕新增奶油、巧克力和水果片");
	}

	public void box() {
		System.out.println("將加好奶油的蛋糕裝入蛋糕盒");
	}

}

雞蛋蛋糕工廠、水果蛋糕工廠:
public class EggCakeFactory extends CakeFactory {

	public Cake makeCake(String name) {

		return new EggCake(name);
	}

}

public class FruitCakeFactory extends CakeFactory {

	public Cake makeCake(String name) {
		return new FruitCake(name);
	}

}

測試程式碼:
public static void main(String[] args) {

		CakeFactory cakeFactory = new FruitCakeFactory();
		Cake cake = cakeFactory.createCake("草莓蛋糕");
		System.out.println(cake.getName());
		cakeFactory = new EggCakeFactory();
		cake = cakeFactory.createCake("蛋黃蛋糕");
		System.out.println(cake.getName());

	}

4.抽象工廠模式

抽象工廠模式:提供一個藉口,用於建立相關或依賴物件的家族,而不要明確制定具體類。


還是用蛋糕店的例子來演示:

抽象類Cake:

public abstract class Cake {
	protected String name;
	protected String cream;
	protected String chocolate;
	protected String condiments;
	
	public abstract void prepare();
	
	public void bake(){
		System.out.println("將蛋糕放進烤箱烘烤");
	}
	
	public void decorate(){
		System.out.println("將" + condiments + "新增到蛋糕上");
	}
	
	public void box(){
	  System.out.println("將蛋糕裝入包裝箱中");
	}
	
	public void makeCake(){
		this.prepare();
		this.bake();
		this.decorate();
		this.box();
	}
	
	public void setName(String name){
		this.name = name;
	}
	
	public String getName(){
		return this.name;
	}

}

抽象類CakeStore:
public abstract class CakeStore {
	
	public abstract Cake createCake(String name);

}

抽象原料工廠:
public abstract class IngredientFactory {
	public abstract String createCream();
	public abstract String createChocolate();
	public abstract String createCondiments();
}
Cake的實現類StrawberryCake:
public class StrawberryCake extends Cake{
    public StrawberryCake(IngredientFactory ingredientFactory){
    	this.ingredientFactory = ingredientFactory;    	
    }
	
	public void prepare() {
         this.cream = this.ingredientFactory.createCream();
         this.chocolate = this.ingredientFactory.createChocolate();
         this.condiments = this.ingredientFactory.createCondiments();
	}	

	private IngredientFactory ingredientFactory = null;
}

抽象原料工廠的實現類CreamIngredientFactory:
public  class CreamIngredientFactory extends IngredientFactory{

	public String createCream() {
		return "酸奶冰淇淋";
	}

	public String createChocolate() {
		return "黑巧克力";
	}

	public String createCondiments() {
		return "草莓片、蘋果片、西瓜片、藍莓片、獼猴桃片";
	}
	
	
	

}
抽象蛋糕店的實現類XXCakeStore:
public class XXCakeStore extends CakeStore{

	public Cake createCake(String name) {
		IngredientFactory ingredientFactory = new CreamIngredientFactory();
		Cake cake = null;
		if("草莓蛋糕".equals(name)){
			cake = new StrawberryCake(ingredientFactory);
			cake.makeCake();
			cake.setName("草莓奶油蛋糕");
			return cake;
		}else{
			//......
		}
		return null;
	}

}
測試程式碼:
public static void main(String[] args) {
		Cake cake = new XXCakeStore().createCake("草莓蛋糕");
		if(cake != null){
			System.out.println(cake.getName());
		}
	}