装饰模式VS代理模式
个人理解
代理模式:我想做,但不能做,我需要有一个能干的人来帮我做
装饰模式:我想做,但不能做,我需要各类特长的人来帮我做,但是我有时需要很多人来帮我做,有时又只需要一个人做。
区别:Proxy模式需要的是一个能人,而Decorator模式需要的是一个团队
代理模式
public interface Greeting {
void sayHello(String name);
}
public class GreetingImpl implements Greeting {
@Override
public void sayHello(String name) {
System.out.println("hello: " + name);
}
}
/**
* 只需要包装GreetingProxy与GreetingImpl实现同一个接口Greeting,
* 并通过构造方法将GreetingImpl传入GreetingProxy中。那么,
* GreetingProxy 就可以完全拥有 GreetingImpl 了。可以在帮它做正事儿之前,
* 先干点别的事情,比如这里的 before() 方法。想干点什么就干点什么,只要您喜欢,它就喜欢。
*/
public class GreetingProxy implements Greeting {
private GreetingImpl greeting;
public GreetingProxy(GreetingImpl greeting) {
this.greeting = greeting;
}
@Override
public void sayHello(String name) {
before();
greeting.sayHello(name);
}
private void before() {
System.out.println("before");
}
}
public class ClientProxy {
public static void main(String[] args) {
Greeting greeting = new GreetingProxy(new GreetingImpl());
greeting.sayHello("chen");
}
}
问题:如果用户现在又来了一个需求:在完成sayHello()之后再需要插入一个数据库?
好的,此时最简单的方法就是给GreetingProxy中增加一个after()方法,再after()方法中完成插入数据库的操作。
那如果此时又改需求,在插入数据库之后,再添加日志。
添加日志之后还需要一些其他的?
这样的话,把所有功能都放在Proxy这个类中是不明智的,同时这也违反了“开闭原则”
此时,我们可以考虑使用Decorator模式,让日志的,数据库的,before的,after的等都独自拥有自己的功能。(此时不再是需要一个人,而是需要一个团队,团队中每个人都有自己的功能,我可以随意搭配)
装饰模式
/**
* 这就是一个非常纯净的装饰器,没有任何的增强逻辑,只是简单的通过构造方法传入Greeting对象,
* 然后调用传入对象的sayHello()方法一样
* 相当于I/O中的FilterInputSream
*/
public class GreetingDecorator implements Greeting {
private Greeting greeting;
public GreetingDecorator(Greeting greeting) {
this.greeting = greeting;
}
@Override
public void sayHello(String name) {
//相当于调用I/O中FileInputSream.read()中的方法
greeting.sayHello(name);
}
}
/**
* 注意:一定是继承GreetingDecorator并不是Greeting,需要继承装饰器,成为一个具体的装饰器
* 相当于I/O中的BufferedInputStream
*/
public class GreetingBefore extends GreetingDecorator {
public GreetingBefore(Greeting greeting) {
super(greeting);
}
@Override
public void sayHello(String name) {
before();
//调用的真正的sayHello方法是构造的时候传递过来的对象的sayHello()
super.sayHello(name);
}
private void before() {
System.out.println("before");
}
}
public class GreetingAfter extends GreetingDecorator {
public GreetingAfter(Greeting greeting) {
super(greeting);
}
private void after() {
System.out.println("after");
}
@Override
public void sayHello(String name) {
super.sayHello(name);
after();
}
}
public class ClientDecorator {
public static void main(String[] args) {
//这里就可以任意的组合了
Greeting greeting = new GreetingAfter(new GreetingBefore(new GreetingImpl()));
greeting.sayHello("chen");
}
}
总结
代理模式和装饰模式都是对类的包装,在不改变类自身的情况下,为类添加特定的功能
所以若对于功能比较单一,可考虑使用Proxy模式,但对于功能较多,且需要动态拓展的情况下,还是适合尝试使用Decorator模式