设计模式--代理模式

Java工程源码

类图

这里写图片描述


定义
为其它对象提供一种代理以控制对这个对象的访问


优点
- 职责清晰 真实的角色就是实现的业务逻辑,不用关心其他非本指责的事务
- 高扩展性 具体主题角色不管怎么变化,只要它实现了接口,代理类完全可以在不做任何修改的情况下使用
- 智能化 动态代理是最好的体现,即在运行阶段才指定实际代理对象(Struts如何把表单元素映射到对象上?)


使用场景
典型应用如Spring AOP,Android AIDL


扩展
- 普通代理 要求客户端只能访问代理角色,而不能访问真实角色
- 强制代理 要求客户端必须通过真实角色找到代理角色(演员和经纪人)
- 虚拟代理 指在需要的时候,才初始化主题对象,可以避免被代理对象太多而引起的初始化缓慢问题

静态代理

抽象主题类

public interface Subject {
    void request();
}

实体主题类

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject->request()");
    }
}

代理类

public class Proxy implements Subject {
    // 要代理哪个实现类
    private Subject subject = null;

    /**
     * 通过构造函数传递被代理者
     *
     * @param subject 被代理者
     */
    public Proxy(Subject subject) {
        this.subject = subject;
    }

    /**
     * 实现接口中定义的方法
     */
    @Override
    public void request() {
        this.before();// 预处理
        this.subject.request();
        this.after();// 善后处理
    }

    /**
     * 预处理
     */
    private void before() {
        System.out.println("预处理");
    }

    /**
     * 善后处理
     */
    private void after() {
        System.out.println("善后处理");
    }
}

静态代理 场景类

public class Client {
    public static void main(String[] args) {
        //新建主题类
        RealSubject realSubject = new RealSubject();
        //代理主题类
        Subject proxySubject = new Proxy(realSubject);
        //执行代理类方法
        proxySubject.request();
    }
}

运行结果

预处理
RealSubject->request()
善后处理

动态代理

玩家接口

public interface IGamePlayer {
    void login(String user, String password);

    void killBoss();

    void upgrade();
}

实体玩家类

public class GamePlayer implements IGamePlayer {
    private String name = "";

    /**
     * 玩家 实现类
     *
     * @param _name 玩家名
     */
    public GamePlayer(String _name) {
        name = _name;
    }

    @Override
    public void killBoss() {
        System.out.println(name + "在打怪");
    }

    @Override
    public void login(String user, String password) {
        System.out.println("登录名为" + user + "的用户  " + name + "登录成功");
    }

    @Override
    public void upgrade() {
        System.out.println(name + "又升了一级");
    }
}

动态代理类 借助java自带的代理方法

public class DynamicProxy implements InvocationHandler {
    /**
     * 被代理者的实例
     */
    private Object obj = null;

    /**
     * 我要代理谁
     *
     * @param _obj 被代理者
     */
    public DynamicProxy(Object _obj) {
        this.obj = _obj;
    }

    /**
     * 执行代理
     *
     * @return 代理类
     */
    public Object proxy() {
        if (obj != null) {
            Class<?> cls = obj.getClass();
            return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this);
        }
        throw new RuntimeException("被代理者为空");
    }

    /**
     * 调用被代理的方法
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result = method.invoke(this.obj, args);
        if (method.getName().equalsIgnoreCase("login")) {
            System.out.println("有人登录");
        } else if (method.getName().equalsIgnoreCase("upgrade")) {
            System.out.println("有人升级了");
        }
        return result;
    }
}

场景类

public class Client {
    public static void main(String[] args) {
        // 新建玩家类
        IGamePlayer player = new GamePlayer("BobbyGu");
        // 动态代理一个玩家类
        IGamePlayer proxyPlayer = (IGamePlayer) new DynamicProxy(player).proxy();
        if (proxyPlayer != null) {
            //调用代理类方法
            proxyPlayer.login("BobbyGu", "123123");
            proxyPlayer.killBoss();
            proxyPlayer.upgrade();
        }
    }
}

运行结果

登录名为BobbyGu的用户  BobbyGu登录成功
有人登录
BobbyGu在打怪
BobbyGu又升了一级
有人升级了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章