一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

java 设计模式之装饰者模式 VS 代理模式详解

时间:2016-08-15 编辑:简简单单 来源:一聚教程网


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

简介 && Java 使用场景

Decorator模式(别名Wrapper):用户扩展功能,动态将职责附加到对象上。使用装饰者比使用继承更加灵活。
我们经常看到的I/O 处理类,实际上就使用到了装饰者模式。

 

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 && 代码实现

 

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 headerViewInfos,
                                 ArrayList 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

 

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 && 代码实现

 

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 源码场景

Binder
WindowManagerImpl.java 代理 WindowManagerGlobal.java
装饰者、代理模式异同

对比

UML

 

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(){} 
}
总结

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

热门栏目