代理模式

来源:互联网 发布:淘宝买啥弓箭好 编辑:程序博客网 时间:2024/04/30 22:07

个人笔记,请不要被误导。

代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。(被代理的对象可以是远程的对象、创建开销大的对象或需要安全控制的对象,下面的三个例子远程代理、虚拟代理和保护代理分别代表这三类)。

实体和代理者实现同一个接口,用户用的时候不用关心究竟是谁,实现用户和实体的解耦。一般代理者都有实体的引用,这样才能调用它。这和适配器模式很相似区别在于前者代理者和实体实现同一个接口。


远程代理:

这里的例子是GumBallMonitor监视GumBallMachine(糖果机)的location、count和State(自己创建的类,表示糖果机状态)。这里用java RMI,它可以帮忙自动创建代理者。需要我们先建立一个远程接口

GumballMachineRemote implements Remote。然后建立远程实体类,它要实现GumballMachineRemote,而且要继承UnicastRemoteObject。这才为GumballMachineRemote接口和远程实体类建立联系,而且能为远程实体类建立代理者,GumballMachineRemote类型的代理者。此外,State类的对象不能被打包,只有序列化的数据类型才可以。所以State类声明时要加上extends Serializable。State类不需要通过网络传来的变量声明为transient。下面要做的就是通过Naming.rebind()方法把远程实体类对象的代理者注册,这里它有一个类似id的东西,以后可以通过Naming.lookUp()方法利用id传回相应远程实体对象的代理者。传回来的代理者类型是远程接口的,这是客户不用关心的。

import java.rmi.Remote;import java.rmi.RemoteException;public interface GumballMachineRemote extends Remote {//考虑是否有风险,所有方法throw RemoteException    public int getCount() throws RemoteException;    public String getLocation() throws RemoteException;    public State getState() throws RemoteException;}
import java.rmi.RemoteException;public class GumballMonitor {    GumballMachineRemote gumballMachineRemote;    public GumballMonitor(GumballMachineRemote gumballMachineRemote){        this.gumballMachineRemote = gumballMachineRemote;    }    public void report(){        try {            gumballMachineRemote.getCount();            gumballMachineRemote.getLocation();            gumballMachineRemote.getState();        } catch (RemoteException e) {            e.printStackTrace();        }    }}


虚拟代理:

这里例子是ImageProxy对象代理ImageIcon对象。因为后者创建的开销太大。加载一个很大的图片时不能一直空白,让用户等,要出现一个loading的图片,提示用户在加载。这个展示loading图片的对象,就是代理者——ImageProxy。ImageProxy判断ImageIcon是否加载完来执行相应操作。

public class ImageProxy implements Icon {    ImageIcon imageIcon;    DocFlavor.URL imageURL;    boolean retrieving = false;    Thread retrievalThread;    public ImageProxy(DocFlavor.URL url){        imageURL = url;    }    @Override    public void paintIcon(Component c, Graphics g, int x, int y) {        if (imageIcon != null) imageIcon.paintIcon(c,g,x,y);        g.drawString("Loading",x + 300,y + 190);        if (!retrieving){            retrieving = true;            retrievalThread = new Thread(new Runnable() {                @Override                public void run() {                    imageIcon = new ImageIcon(String.valueOf(imageURL),"CD Cover");                    c.repaint();                }            });            retrievalThread.start();        }    }    @Override    public int getIconWidth() {        if (imageIcon == null) return 600;        else return imageIcon.getIconWidth();    }    @Override    public int getIconHeight() {        return 0;    }}

保护代理:这是一个动态代理,代码执行之前Proxy类(注意是类!不是对象)还没被创建出来。

java.lang.reflect有自己的代理支持。这里的代理者会调用InvocationHandler类的方法,这里的方法判断客户发的需求,选择执行或不执行,达到保护的目的。

案例里有OwnerInvocationHandler和NonOwnerInvocationHandl两个InvocationHandler类,代理者根据发出请求的是自己还是别人(案例里自己不能改自己被点赞的次数,别人不能改自己的信息)调用这两个类,进行不同的操作。

public class OwnerInvocationHandler implements InvocationHandler {    PersonBean personBean;    public OwnerInvocationHandler(PersonBean personBean){        this.personBean = personBean;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        try {            if (method.getName().startsWith("get")) return method.invoke(personBean,args);            if (method.getName().equals("setHotOrNotRating")) throw new IllegalAccessException();            else if (method.getName().startsWith("set") ) return method.invoke(personBean,args);        }catch (InvocationTargetException e){            e.printStackTrace();        }        return null;    }}
public interface PersonBean {    public String getName();    public void setName(String name);    public int getHotOrNotRating();    public void setHotOrNotRating(int hotOrNotRating);}
import java.lang.reflect.Proxy;public class PersonBeanImpl implements PersonBean {    String name;    int hotOrNotRating;    @Override    public String getName() {        return name;    }    @Override    public void setName(String name) {        this.name = name;    }    @Override    public int getHotOrNotRating() {        return hotOrNotRating;    }    @Override    public void setHotOrNotRating(int hotOrNotRating) {        this.hotOrNotRating = hotOrNotRating;    }    public PersonBean getOwnerProxy(){        return (PersonBean) Proxy.newProxyInstance(this.getClass().getClassLoader(),this.getClass().getInterfaces(),new OwnerInvocationHandler(this));    }}

public void ProxyPattern_Protect(){        PersonBeanImpl personBean = new PersonBeanImpl();        PersonBean ownProxy = personBean.getOwnerProxy();        ownProxy.getHotOrNotRating();        ownProxy.setHotOrNotRating(100);    }