设计模式5-代理模式

一、定义:

为其他对象提供一种代理以控制对这个对象的访问。

二、通用类图:


Subject抽象主题角色

通用代码:

public interface Subject {
    //定义一个方法
    public void request();
}

RealSubject具体主题角色

通用代码:

public class RealSubject implements Subject {
    //实现方法
    public void request() {
        //业务逻辑处理
    }
}

Proxy代理主题角色:负责对真是角色的应用,并做预处理和善后处理工作。

public class Proxy implements Subject {
    //要代理哪个实现类
    private Subject subject = null;
    //默认被代理者
    public Proxy(){
        this.subject = new Proxy();
    }
    //通过构造方法传递代理者
    public Proxy(Object...objects ){
    }
    //实现接口中定义方法
    public void request() {
        this.before();
        this.subject.request();
        this.after();
    }
    //预处理
    private void before(){
        //do something
    }
    //善后处理
    private void after(){
        //do something
    }
}

在通常情况下,一个接口只需要一个代理类就可以了,具体代理哪个实现类由高层模块来决定。可以在代理类Proxy中增加构造函数:

public Proxy(Subject _subject){
    this.subject = _subject;
}

三、使用场景:

Spring AOP是一个非常典型的动态代理。

四、代理模式的扩展

1、普通代理

要求客户端只能访问代理角色,而不能访问真实角色

2、强制代理

强制代理的概念就是要从真实角色查找到代理角色

3、重点:动态代理

动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。即动态产生代理类



Java动态代理类位于java.lang.reflect包下,涉及两个类:

(1)InvocationHandler事务处理器接口中定义方法

Object invoke (Object obj,Method method,Object[] args)

obj代理类,method是被代理的方法,args为方法参数数组。这个抽象方法在代理类中动态实现

(2)Proxy动态代理类

Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)

返回代理类的一个实例,返回的代理类可以当做被代理类使用。


实现步骤:

(1)创建一个实现接口InvocationHandler的类,它必须实现invoke方法

(2)创建被代理的类以及接口

(3)调用Proxy的静态方法,创建一个代理类

(4)通过代理调用方法

下面以玩游戏为例,实现动态代理:

游戏玩儿家接口:

public interface IGamePlayer {
    //登录
    public void login(String user,String password);
    //打怪
    public void killBoss();
    //升级
    public void upgrade();
}

游戏玩儿家实现类:

public class GamePlayer implements IGamePlayer {
    private String name = "";
    public GamePlayer(String name){
        this.name = name;
    }
    public void killBoss() {
        System.out.println(this.name + "打怪");
    }
    public void login(String user, String password) {
        System.out.println("登录名"+user+"的用户"+this.name+"登录成功");
    }
    public void upgrade() {
        System.out.println(this.name + "升级了");
    }
}

事务处理器:

public class GamePlayIH implements InvocationHandler {
    //被代理者实例
    Object obj = null;
    //构造函数
    public GamePlayIH(Object obj){
        this.obj = obj;
    }
    /**
     * /调用被代理的方法
     * @param proxy 被代理的对象
     * @param method 被代理对象的方法
     * @param args 方法参数
     * @return 方法返回值
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("开始代理");
        Object result = method.invoke(this.obj, args);
        System.out.println("结束代理");
        return result;
    }
}

场景类:

public class Client {
    public static void main(String[] args) throws Throwable {
        IGamePlayer player = new GamePlayer("wbao");
        InvocationHandler handler = new GamePlayIH(player);
        ClassLoader cl = player.getClass().getClassLoader();
        //动态产生一个代理者
        IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl, player.getClass().getInterfaces(), handler);
        proxy.login("wbao", "password");
        proxy.killBoss();
        proxy.upgrade();
    }
}

程序执行结果:

开始代理
登录名wbao的用户wbao登录成功
结束代理
开始代理
wbao打怪
结束代理
开始代理
wbao升级了
结束代理

优化:简化场景类调用,增加通知Advice

类图:





猜你喜欢

转载自blog.csdn.net/sinat_27143551/article/details/80195574