设计模式之装饰模式(结构型)
一、模式定义
装饰模式:装饰模式就是允许向一个现有的对象添加新的功能,同时又不改变其结构,装饰模式是一种对象结构型设计模式。
二、模式角色
对于装饰模式可以分为如下角色
- 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();