装饰模式VS代理模式

装饰模式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模式

原文地址:https://www.cnblogs.com/liuligang/p/10543200.html