設計模式入門之裝飾器模式Decorator
阿新 • • 發佈:2017-05-13
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