1. 程式人生 > >設計模式入門之裝飾器模式Decorator

設計模式入門之裝飾器模式Decorator

gravity 減少 都是 一個人 額外 不同的 這也 sys 裝飾器模式

//裝飾模式定義:動態地給一個對象加入一些額外的職責。
//就添加功能來說,裝飾模式比生成子類更為靈活
//這也提現了面向對象設計中的一條基本原則,即:盡量使用對象組合。而不是對象繼承
技術分享
//Component:組件對象的接口。能夠給這些對象動態加入職責
//ConcreateComponet:詳細的組件對象,實現組件對象接口,通常就是被裝飾器裝飾的對象,也就是能夠給這個對象加入職責
//Decorator:全部裝飾器的抽象父類,須要定義一個與組件接口一致的接口。並持有一個Component對象。即被裝飾的對象
//在Java中比較常見的一種裝飾器模式體現例如以下:
//new DataInputStream(new BufferedInputStream(new FileInputStream("IOtest.txt")));
//FileInputStream完畢他自己的功能。然後由裝飾器完畢須要添加的功能
//實例:設計一個獎金系統。獎金有月獎金。累計獎金和團隊獎金,依據不同的人發不同的獎金
//不使用裝飾模式的實現中。各個獎金模塊的耦合非常嚴重,當有新的獎勵方法時修改非常多。擴展不方便
//以下是使用了裝飾模式的實現方式:
//數據庫模擬類,存儲人員銷售額。模擬,僅僅給了一個月的銷售額
public class TempDB {
	private TempDB() {
	}
	public static Map<String, Double> mapMonthSaleMoney = new HashMap<String, Double>();
	static {
		mapMonthSaleMoney.put("張三", 10000.0);
		mapMonthSaleMoney.put("李四", 20000.0);
		mapMonthSaleMoney.put("王五", 30000.0);
	}
}
//全部獎勵方法的父類。標準實現使用了抽象類
public abstract class PrizeCalculor {
	public abstract double calcPrize(String user, Date begin, Date end);
}
//須要被裝飾的對象類,比方每一個人每一個月都會有500塊的基本獎金
public class NormalPrizeCalc extends PrizeCalculor {
	public double calcPrize(String user, Date begin, Date end) {
		return 500;
	}
}
//以下是裝飾器的父類
public abstract class Decorator extends PrizeCalculor{
	protected PrizeCalculor c;//被裝飾的對象
	public Decorator(PrizeCalculor c) {
		this.c = c;
	}
	public double calcPrize(String user, Date begin, Date end) {
		//前後可添加功能
		return this.c.calcPrize(user, begin, end);//默認直接轉調被裝飾對象的方法
	}
}
//月獎金裝飾器類
public class MonthPrizeDecorator extends Decorator{
	public MonthPrizeDecorator(PrizeCalculor c) {
		super(c);
	}
	public double calcPrize(String user, Date begin, Date end) {
		double money = super.calcPrize(user, begin, end);//先獲得被裝飾對象的獎金
		double prize = TempDB.mapMonthSaleMoney.get(user)*0.03;//計算月獎金
		System.out.println(user+"當月業務獎金"+prize);
		return money+prize;//返回被裝飾對象的總獎金
	}
}
//累計獎金裝飾器類,作用同上
public class SumPrizeDecorator extends Decorator{
	public SumPrizeDecorator(PrizeCalculor c) {
		super(c);
	}
	public double calcPrize(String user, Date begin, Date end) {
		double money = super.calcPrize(user, begin, end);
		double prize = 100000*0.001;//如果全部人的累計銷售額都是100000
		System.out.println(user+"累計獎金"+prize);
		return money+prize;
	}
}
//團隊獎金裝飾器類,僅僅有項目經理才有
public class GroupPrizeDecorator extends Decorator{
	public GroupPrizeDecorator(PrizeCalculor c) {
		super(c);
	}
	public double calcPrize(String user, Date begin, Date end) {
		double money = super.calcPrize(user, begin, end);
		double group = 0.0;
		for(double d : TempDB.mapMonthSaleMoney.values()) {
			group += d;
		}
		double prize = group * 0.01;
		System.out.println(user+"當月團隊業務獎金"+prize);
		return money + prize;
	}
}
//client測試類
public class Client {
	public static void main(String[] args) {
		PrizeCalculor calc = new NormalPrizeCalc();
		Decorator d1 = new MonthPrizeDecorator(calc);
		Decorator d2 = new SumPrizeDecorator(d1);
		//把被裝飾對象進行組合,calc對象經d1裝飾,然後d1對象經d2裝飾
		double zs = d2.calcPrize("張三", null, null);
		System.out.println(zs);
		double ls = d2.calcPrize("李四", null, null);
		System.out.println(ls);
		Decorator d3 = new GroupPrizeDecorator(d2);
		//項目經理,d2對象再經d3對象裝飾
		double ww = d3.calcPrize("王五", null, null);
		System.out.println(ww);
	}
}
//裝飾模式的本質:動態組合
//裝飾器模式長處:比繼承更加靈活。更容復用功能,簡化高層定義
//裝飾器模式缺點:會產生非常多細粒度對象
//註意:各個裝飾器之間最好是全然獨立的功能,不要有依賴,這樣在進行裝飾組合的時候。才沒有先後順序的限制,也就是先裝飾誰和後裝飾誰都是一樣的,否則會大大減少裝飾漆組合的靈活性

設計模式入門之裝飾器模式Decorator