转载

设计模式之装饰者模式 VS 代理模式

设计模式之装饰者模式 VS 代理模式

目录

  • 装饰者模式
    • 简介 && Java 使用场景
    • UML && 代码实现
    • Android 源码场景
  • 代理模式
    • 简介 && Java 使用场景
    • UML && 代码实现
    • Android 源码场景
  • 装饰者、代理模式异同
    • 对比
    • 总结

装饰者模式

简介 && Java 使用场景

Decorator模式(别名Wrapper):用户扩展功能,动态将职责附加到对象上。使用装饰者比使用继承更加灵活。

我们经常看到的I/O 处理类,实际上就使用到了装饰者模式。

设计模式之装饰者模式 VS 代理模式

public class DecoratorTest {     public static void main(String[] args) throws IOException {         // 流式读取文件         DataInputStream dis = null;         try{             dis = new DataInputStream(                     new BufferedInputStream(                             new FileInputStream("test.txt")                     )             );              //读取文件内容             byte[] bs = new byte[dis.available()];             dis.read(bs);             String content = new String(bs);             System.out.println(content);         } finally{             dis.close();         }     } }

UML && 代码实现

设计模式之装饰者模式 VS 代理模式

public interface Component {   void operation(); }  public interface Decorator extends Component {   void addedBehavior(); }  public class ConcreteComponent implements Component {   @Override   public void operation() {     System.out.println("operation!");   } }  public class ConcreteDecorator implements Decorator {   private Component decoratedComponent;    public ConcreteDecorator(Component decoratedComponent) {     this.decoratedComponent = decoratedComponent;   }    @Override   public void operation() {     System.out.println("decorated operation!");      decoratedComponent.operation();   }    @Override   public void addedBehavior() {     System.out.println("addedBehaviour!");   } }  public class Client {   public static void main(String[] args) {     Component component = new ConcreteComponent();     component.operation();      // 输出:     // operation!      Decorator decorator = new ConcreteDecorator(component);     smart.operation();     smart.addedBehavior();      // 输出:      // decorated operation!     // operation!     // addedBehaviour!   } }

Android 源码场景

HeaderViewListAdapter.java

public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {      private final ListAdapter mAdapter;      public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos,                                  ArrayList<ListView.FixedViewInfo> footerViewInfos,                                  ListAdapter adapter) {         mAdapter = adapter;          ...     }      ...      public int getCount() {         if (mAdapter != null) {             return getFootersCount() + getHeadersCount() + mAdapter.getCount();         } else {             return getFootersCount() + getHeadersCount();         }     }      ...      public View getView(int position, View convertView, ViewGroup parent) {         // Header (negative positions will throw an IndexOutOfBoundsException)         int numHeaders = getHeadersCount();         if (position < numHeaders) {             return mHeaderViewInfos.get(position).view;         }          // Adapter         final int adjPosition = position - numHeaders;         int adapterCount = 0;         if (mAdapter != null) {             adapterCount = mAdapter.getCount();             if (adjPosition < adapterCount) {                 return mAdapter.getView(adjPosition, convertView, parent);             }         }          // Footer (off-limits positions will throw an IndexOutOfBoundsException)         return mFooterViewInfos.get(adjPosition - adapterCount).view;     }      ...

ContextWrapper.java

设计模式之装饰者模式 VS 代理模式

public class ContextWrapper extends Context {     Context mBase;      public ContextWrapper(Context base) {         mBase = base;     }      ... }

代理模式

简介 && Java 使用场景

代理模式(Proxy):给一个对象提供一个代理,并由代理对象控制对原对象的引用, 对它的客户隐藏一个对象的具体信息。主要用于远程代理、虚拟代理和保护代理。其中保护代理可以进行访问权限控制。

JDK提供的动态代理就使用到了代理模式,用户能够动态的拿到代理类并调用代理方法

public interface Subject {     public void request(); }  public class RealSubject implements Subject {     @Override     public void request()     {         System.out.println("from real subject");     } }  public class MyInvocationHandler implements InvocationHandler {     //持有被代理类的引用     private Subject real;      public MyInvocationHandler(Subject real){         this.real=real;     }      public Object invoke(Object proxy, java.lang.reflect.Method method,             Object[] args) throws Throwable {         //执行被代理对象的方法         Object obj=method.invoke(real, args);         //obj是method方法返回的数据         return obj;     } }  public class DynamicTest {     public static void main(String[] args)     {       Subject real=new RealSubject();       InvocationHandler h=new MyInvocationHandler(real);        //获得被代理类所实现的所有接口的数组,在这里数组中只有Subject.class一个元素       Class[] interfaces= real.getClass().getInterfaces();        //获得类加载器       ClassLoader loader=h.getClass().getClassLoader();        //获得动态代理类的实例       Object s=java.lang.reflect.Proxy.newProxyInstance(loader,interfaces, h);        //通过代理类对象调用方法       Subject sub=(Subject) s;       sub.request();     } }

UML && 代码实现

设计模式之装饰者模式 VS 代理模式

public interface Subject {     public void request(); }  public class RealSubject implements Subject {     @Override     public void request()     {         System.out.println("from real subject");     } }  public class Proxy implements Subject {       private RealSubject realSubject;        public Proxy(Subject realSubject){         this.realSubject = realSubject;     }       @Override     public void request() {           //请求前的操作         preRequest();            realSubject.request();             //请求后的操作          postRequest();       }        private void preRequest(){}        private void postRequest(){}   } 

Android 源码场景

  1. Binder
  2. WindowManagerImpl.java 代理 WindowManagerGlobal.java

装饰者、代理模式异同

对比

UML

设计模式之装饰者模式 VS 代理模式

Decorator类、Proxy类

public class ConcreteDecorator implements Decorator {   private Component decoratedComponent;    public ConcreteDecorator(Component decoratedComponent) {     this.decoratedComponent = decoratedComponent;   }    @Override   public void operation() {     System.out.println("decorated operation!");      decoratedComponent.operation();   }    @Override   public void addedBehavior() {     System.out.println("addedBehaviour!");   } }
public class Proxy implements Subject {       private RealSubject realSubject;        public Proxy(Subject realSubject){         this.realSubject = realSubject;     }       @Override     public void request() {           //请求前的操作         preRequest();            realSubject.request();             //请求后的操作          postRequest();       }        private void preRequest(){}        private void postRequest(){}   } 

总结

  • 装饰器模式关注于在一个对象上动态的添加方法,而代理模式关注于控制对对象的访问。
  • 代理模式是对它的客户隐藏一个对象的具体信息。当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。
  • 装饰器模式的目的不在于控制访问,而是扩展功能。当我们使用装饰器模式的时候,通常的做法是将原始对象作为一个参数传给装饰者的构造器。

参考资料

  • Examples of GoF Design Patterns in Java's core libraries
  • iluwatar/java-design-patterns
  • Android设计模式源码解析之Proxy模式
原文  http://navyblue.top/article/169
正文到此结束
Loading...