高新區(qū)網(wǎng)站建設(shè)的建議免費(fèi)網(wǎng)上申請注冊
裝飾模式
- 裝飾模型
- 裝飾模式示例
- 商場收銀程序(簡單工廠+策略+裝飾模式實(shí)現(xiàn))
- 裝飾模式總結(jié)
裝飾模型
裝飾模式(Decorator),動(dòng)態(tài)地給一個(gè)對象添加一些額外的職責(zé),就增加功能來說,裝飾模式比生成子類更為靈活。
Component 是定義一個(gè)對象接口,可以給這些對象動(dòng)態(tài)地添加職責(zé)。
ConcreateComponent 是定義了一個(gè)具體的對象,也可以給這個(gè)對象添加一些職責(zé)。
Decorator,裝飾抽象類,繼承了 Component,從外類來擴(kuò)展 Component 類的功能,但對應(yīng)Component 來說,是無須知道 Decorator的存在。
ConcreateDecorator 就是具體的裝飾對象,起到給 Component 添加職責(zé)的功能。
// Component類
abstract class Component {public abstract void Operation();
}
// ConcreteComponent類
class ConcreteComponent extends Component {public void Operation() {System.out.println("具體對象的實(shí)際操作");}
}
//Decorator類
abstract class Decorator extends Component {protected Component component;//裝飾一個(gè)Component對象public void SetComponent(Component component) {this.component = component;}//重寫Operation(),實(shí)際調(diào)用component的Operation方法public void Operation() {if (component != null) {component.Operation();}}
}
//ConcreteDecoratorA類
class ConcreteDecoratorA extends Decorator {//本類獨(dú)有子段,以區(qū)別于ConcreteDecoratorB類private String addedState;public void Operation() {//首先運(yùn)行了原有Component的Operation()super.Operation();this.addedState = "具體裝飾對象A的獨(dú)有操作";//再執(zhí)行本類獨(dú)有功能System.out.println(this.addedState);}
}
//ConcreteDecoratorB類
class ConcreteDecoratorB extends Decorator {public void Operation() {//首先運(yùn)行了原有Component的Operation()super.Operation();//再執(zhí)行本類獨(dú)有功能this.AddedBehavior();}//本類獨(dú)有方法,以區(qū)別于ConcreteDecoratorA類private void AddedBehavior() { System.out.println("具體裝飾對象B的獨(dú)有操作");}
}
客戶端代碼
public class Test {public static void main(String[] args){System.out.println("**********************************************"); System.out.println("《大話設(shè)計(jì)模式》代碼樣例");System.out.println(); ConcreteComponent c = new ConcreteComponent();ConcreteDecoratorA d1 = new ConcreteDecoratorA();ConcreteDecoratorB d2 = new ConcreteDecoratorB();//首先用d1來包裝c,擴(kuò)展對象c的方法d1.SetComponent(c); //再用有來包裝d1,擴(kuò)展對象d1的方法d2.SetComponent(d1);//最終執(zhí)行d2的Operation()d2.Operation(); System.out.println();System.out.println("**********************************************");}
}
裝飾模式利用SetComponent來對對象進(jìn)行包裝,這樣每個(gè)裝飾對象的實(shí)現(xiàn)和如何使用這個(gè)對象分離開了,每個(gè)裝飾對象只關(guān)心自己的功能,不需要關(guān)心如何被添加到對象鏈中。
如果只有一個(gè)ConcreteComponent 類而沒有抽象的 Component 類,那么 Decorator 類可以是 ConcreteComponent 的一個(gè)子類。
同樣道理,如果只要一個(gè) ConcreteDecorator 類,那么就沒有必要建立一個(gè)單獨(dú)的 Decorator 類,而可以把 Decorator 和 ConcreteDecorator 的責(zé)任合并成一個(gè)類。
裝飾模式示例
人物形象接口
public interface ICharacter {public void show();
}
具體人類
public class Person implements ICharacter {private String name;public Person(String name) {this.name = name;}public void show() {System.out.println("裝扮的"+name);}
}
服飾類
public class Finery implements ICharacter {protected ICharacter component;public void decorate(ICharacter component) {this.component=component;}public void show() {if (this.component != null){this.component.show();}}
}
具體服飾類(ConcreteDecorator)
public class LeatherShoes extends Finery {public void show(){System.out.print(" 皮鞋");super.show();}
}
public class BigTrouser extends Finery {public void show(){System.out.print(" 垮褲");super.show();}
}
public class TShirts extends Finery {public void show(){System.out.print(" 大T恤");super.show();}
}
public class Tie extends Finery {public void show(){System.out.print(" 領(lǐng)帶");super.show();}
}
public class Suit extends Finery {public void show(){System.out.print(" 西裝");super.show();}
}
public class Strawhat extends Finery {public void show(){System.out.print(" 草帽");super.show();}
}
public class Sneakers extends Finery {public void show(){System.out.print(" 球鞋");super.show();}
}
客戶端代碼
public class Test {public static void main(String[] args){System.out.println("**********************************************"); System.out.println("《大話設(shè)計(jì)模式》代碼樣例");System.out.println(); Person xc = new Person("小菜");System.out.println(" 第一種裝扮:");Sneakers pqx = new Sneakers(); //生成球鞋實(shí)例pqx.decorate(xc); //球鞋裝飾小菜BigTrouser kk = new BigTrouser(); //生成垮褲實(shí)例kk.decorate(pqx); //垮褲裝飾“有球鞋裝飾的小菜”TShirts dtx = new TShirts(); //生成T恤實(shí)例dtx.decorate(kk); //T恤裝飾“有垮褲球鞋裝飾的小菜”dtx.show(); //執(zhí)行形象展示System.out.println(" 第二種裝扮:");LeatherShoes px = new LeatherShoes();//生成皮鞋實(shí)例px.decorate(xc); //皮鞋裝飾小菜Tie ld = new Tie(); //生成領(lǐng)帶實(shí)例ld.decorate(px); //領(lǐng)帶裝飾“有皮鞋裝飾的小菜”Suit xz = new Suit(); //生成西裝實(shí)例xz.decorate(ld); //西裝裝飾“有領(lǐng)帶皮鞋裝飾的小菜”xz.show(); //執(zhí)行形象展示System.out.println(" 第三種裝扮:");Sneakers pqx2 = new Sneakers(); //生成球鞋實(shí)例pqx2.decorate(xc); //球鞋裝飾小菜LeatherShoes px2 = new LeatherShoes();//生成皮鞋實(shí)例px2.decorate(pqx2); //皮鞋裝飾“有球鞋裝飾的小菜”BigTrouser kk2 = new BigTrouser(); //生成垮褲實(shí)例kk2.decorate(px2); //垮褲裝飾“有皮鞋球鞋裝飾的小菜”Tie ld2 = new Tie(); //生成領(lǐng)帶實(shí)例ld2.decorate(kk2); //領(lǐng)帶裝飾“有垮褲皮鞋球鞋裝飾的小菜”Strawhat cm2 = new Strawhat(); //生成草帽實(shí)例cm2.decorate(ld2); //草帽裝飾“有領(lǐng)帶垮褲皮鞋球鞋裝飾的小菜”cm2.show(); //執(zhí)行形象展示System.out.println();System.out.println("**********************************************");}
}
商場收銀程序(簡單工廠+策略+裝飾模式實(shí)現(xiàn))
ISale接口:用作裝飾模式里的 Component。
CashNormal: 用作裝飾模式里的 ConcreteComponent。
CashSuper: 用作裝飾模式里的 Decorator 。
CashReturn:用作裝飾模式里的 ConcreateDecorator 。
public interface ISale {public double acceptCash(double price,int num);
}
// 正常收費(fèi),原價(jià)返回
public class CashNormal implements ISale {public double acceptCash(double price,int num){return price * num;}
}
public class CashSuper implements ISale {protected ISale component;//裝飾對象public void decorate(ISale component) {this.component=component;}public double acceptCash(double price,int num){var result = 0d;if (this.component != null){//若裝飾對象存在,則執(zhí)行裝飾的算法運(yùn)算result = this.component.acceptCash(price,num); }return result;}
}
public class CashRebate extends CashSuper {private double moneyRebate = 1d;//打折收費(fèi)。初始化時(shí)必需輸入折扣率。八折就輸入0.8public CashRebate(double moneyRebate){this.moneyRebate = moneyRebate;}//計(jì)算收費(fèi)時(shí)需要在原價(jià)基礎(chǔ)上乘以折扣率public double acceptCash(double price,int num){double result = price * num * this.moneyRebate;return super.acceptCash(result,1);}
}public class CashReturn extends CashSuper {private double moneyCondition = 0d; //返利條件private double moneyReturn = 0d; //返利值//返利收費(fèi)。初始化時(shí)需要輸入返利條件和返利值。//比如“滿300返100”,就是moneyCondition=300,moneyReturn=100public CashReturn(double moneyCondition,double moneyReturn){this.moneyCondition = moneyCondition;this.moneyReturn = moneyReturn;}//計(jì)算收費(fèi)時(shí),當(dāng)達(dá)到返利條件,就原價(jià)減去返利值public double acceptCash(double price,int num){double result = price * num;if (moneyCondition>0 && result >= moneyCondition)result = result - Math.floor(result / moneyCondition) * moneyReturn; return super.acceptCash(result,1); }
}
public class CashContext {private ISale cs; //聲明一個(gè)ISale接口對象 //通過構(gòu)造方法,傳入具體的收費(fèi)策略public CashContext(int cashType){switch(cashType){case 1:this.cs = new CashNormal();break;case 2:this.cs = new CashRebate(0.8d);break;case 3:this.cs = new CashRebate(0.7d);break;case 4:this.cs = new CashReturn(300d,100d);break;case 5://先打8折,再滿300返100// 裝飾模式CashNormal cn = new CashNormal();CashReturn cr1 = new CashReturn(300d,100d); CashRebate cr2 = new CashRebate(0.8d);cr1.decorate(cn); //用滿300返100算法包裝基本的原價(jià)算法cr2.decorate(cr1); //打8折算法裝飾滿300返100算法this.cs = cr2; //將包裝好的算法組合引用傳遞給cs對象break;case 6://先滿200返50,再打7折// 裝飾模式CashNormal cn2 = new CashNormal();CashRebate cr3 = new CashRebate(0.7d);CashReturn cr4 = new CashReturn(200d,50d); cr3.decorate(cn2); //用打7折算法包裝基本的原價(jià)算法cr4.decorate(cr3); //滿200返50算法裝飾打7折算法this.cs = cr4; //將包裝好的算法組合引用傳遞給cs對象break;}}public double getResult(double price,int num){// 根據(jù)收費(fèi)策略的不同,獲得計(jì)算結(jié)果return this.cs.acceptCash(price,num);}
}
客戶端代碼
public class Test {public static void main(String[] args){System.out.println("**********************************************"); System.out.println("《大話設(shè)計(jì)模式》代碼樣例");System.out.println(); int discount = 0; //商品折扣模式double price = 0d; //商品單價(jià)int num = 0; //商品購買數(shù)量double totalPrices = 0d;//當(dāng)前商品合計(jì)費(fèi)用double total = 0d; //總計(jì)所有商品費(fèi)用Scanner sc = new Scanner(System.in);do {System.out.println("商品折扣模式如下:"); System.out.println("1.正常收費(fèi)"); System.out.println("2.打八折"); System.out.println("3.打七折"); System.out.println("4.滿300送100"); System.out.println("5.先打8折,再滿300送100"); System.out.println("6.先滿200送50,再打7折"); System.out.println("請輸入商品折扣模式:"); discount = Integer.parseInt(sc.nextLine());System.out.println("請輸入商品單價(jià):"); price = Double.parseDouble(sc.nextLine());System.out.println("請輸入商品數(shù)量:"); num = Integer.parseInt(sc.nextLine());System.out.println(); if (price>0 && num>0){//根據(jù)用戶輸入,將對應(yīng)的策略對象作為參數(shù)傳入CashContext對象中CashContext cc = new CashContext(discount);//通過Context的getResult方法的調(diào)用,可以得到收取費(fèi)用的結(jié)果//讓具體算法與客戶進(jìn)行了隔離totalPrices = cc.getResult(price,num);total = total + totalPrices;System.out.println(); System.out.println("單價(jià):"+ price + "元 數(shù)量:"+ num +" 合計(jì):"+ totalPrices +"元"); System.out.println();System.out.println("總計(jì):"+ total+"元"); System.out.println();}}while(price>0 && num>0);System.out.println();System.out.println("**********************************************");}
}
裝飾模式總結(jié)
裝飾模式是為已有功能動(dòng)態(tài)地添加更多功能的一種方式。
當(dāng)系統(tǒng)需要新功能的時(shí)候,是向舊的類中添加新的代碼。這些新加的代碼通常裝飾了原有類的核心職責(zé)或主要行為,但這種做法的問題在于,它們在主類中加入了新的字段,新的方法和新的邏輯,從而增加了主類的復(fù)雜度。
裝飾模式卻提供了一個(gè)非常好的解決方案,它把每個(gè)要裝飾的功能放在單獨(dú)的類中,并讓這個(gè)類包裝它所要裝飾的對象,因此,當(dāng)需要執(zhí)行特殊行為時(shí),客戶代碼就可以在運(yùn)行時(shí)根據(jù)需要有選擇地、按順序地使用裝飾功能包裝對象了。
把類中的裝飾功能從類中搬移去除,這樣可以簡化原有的類。這樣做的好處就是有效地把類的核心職責(zé)和裝飾功能區(qū)分開了。