設計模式之裝飾模式(結構型)
一、模式定義
裝飾模式:裝飾模式就是允許向一個現有的物件新增新的功能,同時又不改變其結構,裝飾模式是一種物件結構型設計模式。
二、模式角色
對於裝飾模式可以分為如下角色
- Component:抽象構件
- ConcreteComponent:具體構件
- Decorator:抽象裝飾類
- ConcreteDecorator:具體裝飾類
三、模式分析
對於裝飾模式進行解釋,更易於理解。要給一個類或物件新增行為,一般有兩種方法,一種是繼承方法,通過類繼承的方法可以使Z子類擁有自身方法的同時,擁有父類的方法這就是一種新增類行為的方法;對於另外一種新增類行為的方法就是關聯方法,即將一個類嵌入另外一個類,對於這個類,我們稱之為裝飾器(Decorator)
上面說了繼承機制和關聯機制,對於關聯機制與繼承機制相比,關聯優勢在於不會破壞類的封裝性,繼承的耦合度還是比關聯要大的,所以應用關聯機制的裝飾模式偶爾度還是比較小的,這個就是裝飾模式的優點了,不過裝飾模式需要建立比較多的物件,這種缺點或許可以用享元模式減少類的建立。
下面給出裝飾模式的經典程式碼:
繼承抽象構件介面
public class Decorator extends Component { private Component component; public Decorator(Component component) { this.component=component; } public void operation() { component.operation(); } }
具體裝飾型別實現抽象裝飾介面
public class ConcreteDecorator extends Decorator { public ConcreteDecorator(Component component) { super(component); } public void operation() { super.operation(); addedBehavior(); } public void addedBehavior() { //新增方法 } }
四、模式例子
給出《設計模式》 一書的多重加密例子:
某系統提供了一個數據加密功能,可以對字串進行加密。最簡單的加密演算法通過對字母進行移位來實現,同時還提供了稍複雜的逆向輸出加密,還提供了更為高階的求模加密。使用者先使用最簡單的加密演算法對字串進行加密,如果覺得還不夠可以對加密之後的結果使用其他加密演算法進行二次加密,當然也可以進行第三次加密。現使用裝飾模式設計該多重加密系統。
抽象構件介面:
public interface Cipher { public String encrypt(String plainText); }
具體構件類:
public final class SimpleCipher implements Cipher { public String encrypt(String plainText) { String str=""; for(int i=0;i<plainText.length();i++) { char c=plainText.charAt(i); if(c>='a'&&c<='z') { c+=6; if(c>'z') c-=26; if(c<'a') c+=26; } if(c>='A'&&c<='Z') { c+=6; if(c>'Z') c-=26; if(c<'A') c+=26; } str+=c; } return str; } }
抽象裝飾類:
public abstract class CipherDecorator implements Cipher { private Cipher cipher; public CipherDecorator(Cipher cipher) { this.cipher=cipher; } public String encrypt(String plainText) { return cipher.encrypt(plainText); } }
具體裝飾類:
public class AdvancedCipher extends CipherDecorator { public AdvancedCipher(Cipher cipher) { super(cipher); } public String encrypt(String plainText) { String result=super.encrypt(plainText); result=mod(result); return result; } public String mod(String text) { String str=""; for(int i=0;i<text.length();i++) { String c=String.valueOf(text.charAt(i)%6); str+=c; } return str; } }
public class ComplexCipher extends CipherDecorator { public ComplexCipher(Cipher cipher) { super(cipher); } public String encrypt(String plainText) { String result=super.encrypt(plainText); result= this.reverse(result); return result; } public String reverse(String text) { String str=""; for(int i=text.length();i>0;i--) { str+=text.substring(i-1,i); } return str; } }
客戶端類進行呼叫:
public class Client { public static void main(String args[]) { String password="sunnyLiu";//明文 String cpassword;//密文 Cipher sc,ac,cc; sc=new SimpleCipher(); cpassword=sc.encrypt(password); System.out.println(cpassword); cc=new ComplexCipher(sc); cpassword=cc.encrypt(password); System.out.println(cpassword); ac=new AdvancedCipher(cc); cpassword=ac.encrypt(password); System.out.println(cpassword); } }
模式應用
裝飾模式應用最常見的就是JDK提供的Java IO操作
- 抽象構件類:InputStream
- 具體構件類:FileInputStream、ByteArrayInputStream等
- 抽象裝飾類:FilterInputStream
-
具體裝飾類:BufferedInputStream、DataInputStream等
...
五、模式分類
裝飾模式可以分為透明裝飾模式和半透明裝飾模式。
透明裝飾模式
透明裝飾模式要求客戶端面向抽象程式設計,裝飾模式的透明性要求客戶端程式不應該宣告具體構件型別和具體裝飾型別,而應該全部宣告為抽象構件型別。
Cipher sc,cc,ac; sc=new SimpleCipher(); cc=new ComplexCipher(sc); ac=new AdvancedCipher(cc);
半透明裝飾模式
半透明裝飾模式是比較常見的,大多數裝飾模式都是半透明(semi-transparent)的裝飾模式,而不是完全透明(transparent)的,即允許使用者在客戶端宣告具體裝飾者型別的物件,呼叫在具體裝飾者中新增的方法。
Transform camaro; camaro=new Car(); camaro.move(); Robot bumblebee=new Robot(camaro); bumblebee.move(); bumblebee.say();