歡迎收看俗到掉渣的《小Y講堂》節目,大家好,我是小Y,一個集性感毛髮與才華於一身的程式猿。小Y的設計模式系列中的**「代理模式」和「裝飾模式」**在前面已經總結過了,又是時候嘮叨嘮叨這兩者之間在《魂鬥羅歸來》中的是是非非了。
一、模式介紹
1.通用UML的對比
從上圖可以看到,代理模式和裝飾模式的類圖非常類似,裝飾模式可以說是代理模式的一個特殊應用,兩者的共同點是都具有相同的介面。
2.模式的介紹
- 代理模式,為其他物件提供一種代理以控制物件的訪問。
- 裝飾模式,動態地給物件新增一些額外的職責,可以通過使用不同的具體裝飾類以及這些裝飾類的排列組合,創造出很多不同行為的組合。
### 小Y,你搞什麼呀?都嘮叨老半天了,怎麼還不進入正題呀,區別區別!!!
### 客官,別急別急,小Y馬上帶你去爽爽…千萬別想歪,我們是要幹正事的!!我們的叼煙大漢比爾·雷澤馬上就要跟大家見面。
二、代理模式下比爾·雷澤的武器輸出
1.代理模式下武器輸出的UML
2.代理模式下武器輸出的程式碼實現
①武器輸出介面類
public interface IWeapon {
void output();
}
複製程式碼
②打小兵選擇G5手雷輔助攻擊
public class PlayCreeps implements IWeapon {
@Override
public void output() {
System.out.print("散彈槍進行掃射!G5手雷輔助攻擊!");
}
}
複製程式碼
③打大機選擇集速手雷輔助
public class PlayBigMachine implements IWeapon {
@Override
public void output() {
System.out.print("散彈槍進行掃射!集速手雷輔助!");
}
}
複製程式碼
④小Y代理
public class 小Y_Proxy implements IWeapon {
private IWeapon weapon;
public 小Y_Proxy(IWeapon weapon) {
this.weapon=weapon;
}
@Override
public void output() {
weapon.output();
}
}
複製程式碼
⑤Client實現
public class Client {
public static void main(String[] args){
//打小兵使用G5手雷輔助
PlayCreeps playCreeps=new PlayCreeps();
小Y_Proxy 小Y_proxy=new 小Y_Proxy(playCreeps);
小Y_proxy.output();
//打大機使用集速手雷輔助
PlayBigMachine playBigMachine=new PlayBigMachine();
小Y_Proxy 小Y_proxy1=new 小Y_Proxy(playBigMachine);
小Y_proxy1.output();
}
}
複製程式碼
輸出的結果為:
①散彈槍進行掃射!G5手雷輔助攻擊!
②散彈槍進行掃射!集速手雷輔助!
複製程式碼
從實現程式碼中可以看出,在不改變介面的前提下,對武器輸出進行控制。比爾·雷澤用什麼武器有小Y決定的,小Y讓比爾·雷澤攜帶打小兵型武器他就得帶,小Y對比爾·雷澤的武器輸出有絕對的控制權。
三、裝飾模式下比爾·雷澤的武器輸出
1.裝飾模式下武器輸出類圖
2.裝飾模式下武器輸出的程式碼實現
①武器輸出介面類
public interface IWeapon {
void output();
}
複製程式碼
②武器輸出裝飾抽象類
public abstract class PlayDecorator implements IWeapon {
private IWeapon weapon;
public PlayDecorator(IWeapon weapon) {
this.weapon = weapon;
}
@Override
public void output() {
weapon.output();
}
}
複製程式碼
③打小兵使用G5手雷輔助攻擊
public class PlayCreeps extends PlayDecorator {
public PlayCreeps(IWeapon weapon) {
super(weapon);
}
@Override
public void output() {
super.output();
System.out.print("G5手雷輔助攻擊!");
}
}
複製程式碼
④打大機使用集速手雷輔助
public class PlayBigMachine extends PlayDecorator {
public PlayBigMachine(IWeapon weapon) {
super(weapon);
}
@Override
public void output() {
super.output();
System.out.print("集速手雷輔助!");
}
}
複製程式碼
⑤實現角色比爾·雷澤(對它進行裝飾)
public class BillRizer implements IWeapon {
@Override
public void output() {
//角色最基本的技能
System.out.print("散彈槍進行掃射!");
}
}
複製程式碼
⑥Client實現
public class Client {
public static void main(String[] args){
//需要裝飾的BillRizer
BillRizer billRizer=new BillRizer();
//打小兵使用G5手雷輔助
PlayCreeps playCreeps=new PlayCreeps(billRizer);
playCreeps.output();
//打大機使用集速手雷輔助
PlayBigMachine playBigMachine=new PlayBigMachine(playCreeps);
playBigMachine.output();
}
}
複製程式碼
輸出的結果為:
①散彈槍進行掃射!G5手雷輔助攻擊!
②散彈槍進行掃射!G5手雷輔助攻擊!集速手雷輔助!
複製程式碼
- 裝飾類對被裝飾類的行為沒有決定權,只有加強作用,它不決定被代理的方法是否被執行,只是起到增強或者減弱被代理的功能。比爾·雷澤的武器輸出並不固定,在輸出的過程中還可以通過組合確定。
- 裝飾模式的本質是動態組合。每個裝飾類負責新增一些額外的功能,然後通過組合為被裝飾類新增負複雜功能,每個裝飾類的職責比較簡單,增加可重用性,符合單一職責原則。
三、小結
- 代理模式目標是控制對被代理物件的訪問,把當前的行為或功能委託給其他物件執行,不對被代理物件做任何的處理,負責介面限定;裝飾模式是在要保證介面不變的情況下加強類的功能,保證的是被裝飾的物件功能比原始的豐富或者減弱。
- 代理類所代理的類的行為完全由代理類確定;裝飾模式的物件需要根據實際組合來確定。