装饰器模式
简介
装饰器模式是基于对象组合的方式(CRP 合成复用原则)来动态的给对象添加所需要的功能。
装饰器会持有一个构件对象的实例。
示例
// 对应于图片中Componet
public interface Coat {
public void show();
}
// 对应于ConcreteComponent
public class CoatImpl implements Coat {
@Override public void show() {
System.out.println("原始show方法");
}
}
//对应于ConcreteDecorator
public class TDress implements Coat {
//持有实现接口对象的引用
public Coat coat;
public TDress(Coat coat) {
super();
this.coat = coat;
}
@Override public void show() {
System.out.println("TDress 装饰器前");
coat.show();
System.out.println("TDress 装饰器后");
}
}
//对应于ConcreteDecorator
public class Tshirt implements Coat {
public Coat coat;
public Tshirt(Coat coat) {
super();
this.coat = coat;
}
@Override public void show() {
System.out.println("Tshirt 装饰器前");
coat.show();
System.out.println("Tshirt 装饰器后");
}
}
//客户端测试类
public class Test {
public static void main(String[] args) {
//客户端应当声明Component对象
Coat coat = new CoatImpl();
Coat Tshirt = new Tshirt(coat);
Tshirt.show();
Coat TDress = new TDress(coat);
TDress.show();
}
}
扩展及应用
装饰器模式意味着在不改变接口的情况下,增强对象的功能。但在实际应用中,往往需要添加新的公开方法,即“半透明”式装饰器。即允许装饰器改变接口,增加新方法。此时客户端使用的是具体的ConcreteDecorator对象。
java中的典型应用举例:
InputStream代表Component对象。
FileInputStream代表ConcreteComponent对象。
FilterInputStream代表Decorator对象,并持有InputStream的对象实例的引用。
BufferedInputStream、DataInputStream等代表ConcreteDecorator对象。
String pathname = "home/upsmart/input.txt";
File filename = new File(pathname);
InputStreamReader reader = new InputStreamReader( new FileInputStream(filename));
BufferedReader br = new BufferedReader(reader);
public abstract class InputStream implements Closeable {
......
}
public class FileInputStream extends InputStream
{
......
}
public class FilterInputStream extends InputStream {
protected volatile InputStream in;
protected FilterInputStream(InputStream in) {
this.in = in;
......
}
策略模式
简介
是对算法的封装,把使用算法的责任和算法本身分割开来,委托给不同的对象管理。其可用于多重条件的判断。但其缺点也很明显,所有策略类都需要对外暴露。
示例
// context类
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
super();
this.strategy = strategy;
}
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public int calculate(int a, int b) {
return strategy.calculate(a, b);
}
}
//Strategy接口
public interface Strategy {
public int calculate(int a, int b);
}
//具体策略实现类
public class AddStrategy implements Strategy {
@Override public int calculate(int a, int b) {
return a + b;
}
}
//具体策略实现类
public class SubstractStrategy implements Strategy {
@Override public int calculate(int a, int b) {
return a - b;
}
}
// 客户端测试类,客户端需要知道所有的策略类
public class Test {
public static void main(String[] args) {
//加法
Context context=new Context(new AddStrategy());
System.out.println(context.calculate(10, 5));
//减法
Context context2=new Context(new SubstractStrategy());
System.out.println(context2.calculate(3, 2));
}
}
扩展及应用
Spring中的代理对象的创建
其中ProxyFactoryBean代表Context角色,通过依赖的方法来关联具体策略对象,通过调用策略对象的getProxy(ClassLoader classLoader)方法来完成操作。其根据条件选择JDK代理方式还是CGLIB方式。
其中AopProxy代表Strategy角色,Cglib2AopProxy和JdkDynamicAopProxy分别代表具体的策略模式。
AopProxyFactory、DefaultAopProxyFactory、ProxyCreatorSupport主要负责创建具体的策略对象。