参考文章:装饰器模式和代理模式的区别

https://www.cnblogs.com/ealenxie/p/9896269.html
最近有时间,学习了一下设计模式,发现了一个问题,代理模式(静态代理)在写法和结构上,基本和装饰器是一样的。
由此引发了对这两者的真正区别的思考,网上搜索了许许多多的答案(虽然都有一定的道理,个人觉得都没有说到真正的重点) :
1 . 有的人说是结构上不同,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰器能够在运行时递归地被构造(我个人完全反对这种说法);
2 . 装饰器模式为了增强功能;而代理模式是为了加以控制,代理类对被代理的对象有控制权,决定其执行或者不执行。(大名鼎鼎的菜鸟教程这样解释);
3 . 甚至还有人说装饰器模式用于添加新方法;而代理模式则用于增强原方法(那为什么叫代理?)。

代理模式(静态)与装饰者虽然在结构上基本上一模一样,但两者却有真正区别,我认为是 : 目的不一样,关注的重心不一样。
代理模式目的 : 让原有对象被代理,我们的目的是让使用者尽可能的感受不到原有对象,原有对象的行为或额外的动作交由代理对象完成。(完成代理模式的真正意义)
装饰器模式目的 : 让原有对象被增强,我们的目的通常是得到由原有对象被增强后的装饰器对象行为。(完成装饰器模式的真正意义)
代理模式关注重心 : 主要功能不变,代理对象只是帮忙代理或稍加扩展原有对象的行为,功能上主要关心原有对象所具有的行为。(最终主要功能仍然由原有对象决定)
装饰器模式关注重心 : 主要功能增强,使用装饰器目的就是为了增强,功能上更关心装饰增加后的行为。(最终主要功能由装饰对象决定)

静态代理

静态代理的角色分为 : 抽象行为角色,委托人,代理人。基本写法如下 :
抽象行为角色 : 是委托人和代理人的共同接口。这里我们叫它抽象主题(Subject) :

  1. package name.ealen.proxy.designPattern.staticProxy;
  2. /**
  3. * Created by EalenXie on 2018/11/2 10:16.
  4. */
  5. public interface Subject {
  6. public void operation();
  7. }

委托人 : 也就是我上面一直说的原有对象,真正被代理的对象,也叫做代理元。这里我们叫它真实主题 (RealSubject):

  1. package name.ealen.proxy.designPattern.staticProxy;
  2. /**
  3. * Created by EalenXie on 2018/11/2 10:17.
  4. */
  5. public class RealSubject implements Subject {
  6. @Override
  7. public void operation() {
  8. System.out.println("真实对象 : 重要操作");
  9. }
  10. }

代理人 : 代理角色,由它去代理原有对象。它包含被代理对象的引用,这里叫它代理主题(ProxySubject):

  1. public class ProxySubject implements Subject {
  2. private Subject subject;
  3. public ProxySubject(Subject subject) {
  4. this.subject = subject;
  5. }
  6. /**
  7. * 目的 : 代理真实对象完成方法调用,代理可以进行相对不重要的行为扩展
  8. */
  9. @Override
  10. public void operation() {
  11. before();
  12. subject.operation();
  13. after();
  14. }
  15. private void after() {
  16. System.out.println("代理人 : 真实对象的操作完成了");
  17. }
  18. private void before() {
  19. System.out.println("代理人 : 开始完成真实对象的操作");
  20. }
  21. }

测试代码 :

  1. /**
  2. * 静态代理
  3. */
  4. @Test
  5. public void staticProxy() {
  6. //一个真实对象
  7. Subject realSubject = new RealSubject();
  8. //一个代理人,指定要代理的真实对象,类型只能是Subject及其子类
  9. Subject proxy = new ProxySubject(realSubject);
  10. //整个操作由代理人帮真实对象完成,代理人还做了操作说明
  11. proxy.operation();
  12. }