设计模式-装饰模式
装饰模式是为已有功能动态的添加更多功能的一种方式,可以有效地把类的核心职责和装饰功能区分开
装饰模式的实现有透明与半透明的区别,差别在于具体装饰类是否新增了抽象接口不存在的方法或属性。比如上面的类图就是半透明装饰模式,因为两个具体装饰类新增了addedStatus 和 addedBehavior,将这两个方法/属性去掉,就符合了透明装饰模式。
透明与半透明各有优劣,透明装饰模式在客户端使用时是以抽象接口为句柄初始化的,所以可以多层装饰。而半透明是用具体装饰类作为句柄,设计比较简单灵活,但是无法多次装饰了。
下面再举一个透明装饰模式的例子
你有一家面馆,只卖面
首先有一个面的接口
public interface Noodles {
String getDes();
}
然后有两种不同的面
public class HandPulledNoodles implements Noodles {
@Override
public String getDes() {
return "a bowl of Hand-Pulled Noodles";
}
}
public class SlicedNoodles implements Noodles {
@Override
public String getDes() {
return "a bowl of Sliced Noodles";
}
}
装饰器定义
public abstract class NoodlesDecorator implements Noodles {
private Noodles noodles = null;
public NoodlesDecorator(Noodles noodles) {
this.noodles = noodles;
}
abstract String getDecoration();
@Override
public String getDes() {
return noodles.getDes() + ", " + getDecoration();
}
}
有两种装饰选择:不要葱和加个蛋
public class NoOnions extends NoodlesDecorator {
public NoOnions(Noodles noodles) {
super(noodles);
}
@Override
String getDecoration() {
return "no onions";
}
}
public class AddEgg extends NoodlesDecorator {
public AddEgg(Noodles noodles) {
super(noodles);
}
@Override
String getDecoration() {
return "add an egg";
}
}
测试
public class Ordering {
public static void main(String[] args) {
Noodles noodles1 = new NoOnions(new HandPulledNoodles());
System.out.println(noodles1.getDes());
Noodles noodles2 = new NoOnions(new AddEgg(new SlicedNoodles()));
System.out.println(noodles2.getDes());
}
}
在Java中其实我们很熟悉的IO,也在api中大量使用了装饰模式的设计,比如
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), charset));