1. 程式人生 > >設計模式之組合模式三

設計模式之組合模式三

設計模式之組合模式三

六、享元模式

七、外觀模式

六、享元模式

核心:
1)享元模式以共享的方式高效的支援大量細粒度物件的重用
2)享元模式物件能做到共享的關鍵是區分了內部狀態和外部狀態
內部狀態:可以共享,不會隨環境變化而變化
外部狀態:不可以共享,會隨環境變化而變化

享元模式的實現:
1)FlyWeightFactory享元工廠類
建立並管理享元物件,享元池一般設計成鍵值對
2)FlyWeight抽象享元對類
通常是一個介面或抽象類,宣告公共法,這些方法可以向外界提供物件的內部狀態,設定外部狀態
3)ConcreteFlyWeight具體享元類
為內部狀態提供成員變數進行儲存
4)UnsharedConcreteFlyWeight非共享享元類
不能被共享的子類可以設計為非共享享元類

例項:五子棋

ChessFlyWeight

package com.flyWeight;

/**
 * 抽象享元類
 */
public interface ChessFlyWeight {
    void setColor(String color);//設定棋子顏色
    String getColor();//得到棋子顏色
    void display(Coordinate coordinate);//顯示棋子位置
}

/**
 * 具體享元類
 */
class ConcreteFlyWeight implements ChessFlyWeight {
    //棋子顏色
    private String color;
    
    //構造器
    public ConcreteFlyWeight(String color) {
    	this.color = color;
    }
    
    @Override
    public void setColor(String color) {
    	this.color = color;
    }
    
    @Override
    public String getColor() {
    	return this.color;
    }
    
    @Override
    public void display(Coordinate coordinate) {
	    System.out.println("棋子顏色:"+this.color);
	    System.out.println("棋子位置:"+coordinate.getX()+"-----"+coordinate.getY());
    }
}

Coordinate

/**
 * UnsharedFlyWeight非共享享元類
 */
package com.flyWeight;

public class Coordinate {
    //棋子的位置
    private int x,y;
    
    public Coordinate(int x, int y) {
	    this.x = x;
	    this.y = y;
    }
    
    public int getX() {
    	return x;
    }
    
    public void setX(int x) {
    	this.x = x;
    }
    
    public int getY() {
    	return y;
    }
    
    public void setY(int y) {
    	this.y = y;
    }
}

ChessFlyWeightFactory

/**
 * 享元工廠類
 */
package com.flyWeight;

import java.util.HashMap;
import java.util.Map;

public class ChessFlyWeightFactory {

    //享元池(即容器)
    private static Map<String,ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>();
    
    /**
     * 得到棋子
     * @param color 棋子顏色
     * @return 棋子資訊
     */
    public static ChessFlyWeight getChess(String color) {
	    //如果有此color的棋子
	    if(map.get(color)!=null){
	    //返回該顏色的棋子資訊
	    return map.get(color);
	    }else{
		//沒有此顏色的棋子
	    //建立該顏色的棋子
	    ChessFlyWeight chessFlyWeight = new ConcreteFlyWeight(color);
	    //將該棋子放入享元池中
	    map.put(color,chessFlyWeight );
	    //返回該棋子的資訊
	    return map.get(color);
	    }
    }
}

Client

package com.flyWeight;

public class Client {
    public static void main(String[] args) {
    //建立兩個黑色棋子,共享一個
    ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");
    ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");
    //顯示這兩個棋子
    System.out.println(chess1);
    System.out.println(chess2);
    
    //將棋子放置不同的位置
    chess1.display(new Coordinate(10,10 ));
    chess2.display(new Coordinate(20,20 ));
    }
}

結果:

[email protected]
[email protected]
棋子顏色:黑色
棋子位置:10-----10
棋子顏色:黑色
棋子位置:20-----20

享元模式應用場景:
享元模式由於其共享的特性,可以在任何“池”中操作,如執行緒池、資料庫連線池
String類的設計也是享元模式

優點:
1)極大減少記憶體中物件的數量
2)相同或相似的物件記憶體只有一份,極大的節約資源,提高系統性能
3)外部狀態相對獨立,不影響內部狀態

缺點:
1)模式較為複雜,使程式邏輯複雜化
2)為了節省記憶體,共享了內部狀態,分離出外部狀態,而讀取外部狀態使執行時間變長,用時間換取了空間

七、外觀模式

迪米特法則(最少知識原則)
當一個軟體實體應當儘可能少的與其他實體發生相互作用,外觀模式為子系統提供統一的入門,封裝子系統的複雜性,便於客戶端呼叫