代理模式

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

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

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


远程代理:

这里的例子是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);
    }






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值