Android知识Android开发Android技术知识

代理模式

2017-04-21  本文已影响77人  程序员丶星霖

代理模式

定义

代理模式(Proxy Pattern)也叫委托模式,是构造型的设计模式之一,就是给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。
英文定义:Provide a surrogate or placeholder for another object to control access to it .

代理模式的UML图示如下所示:

代理模式.jpg

上图中主要涉及如下角色:

代理模式的通用代码如下所示:

//抽象主题类
public interface Subject{
    //定义一个方法
    public void request();
}
//真实主题类
public class RealSubject implements Subject{
    //实现方法
    public void request(){
        //业务逻辑处理
    }
}
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
    }
}

优缺点

优点:

什么时候要使用代理模式?
在对已有的方法进行使用时出现需要对原有方法进行改进或者修改时,有两种改进选择:

下面是常见的几种代理模式:

代理模式一般应用于以下情况:

扩展

1.普通代理

在网络上代理服务器设置分为透明代理和普通代理。
透明代理:就是用户不用设置代理服务器地址,就可以直接访问,也就是说代理服务器对用户来说是透明的,不用知道它存在的。
普通代理:需要用户自己设置代理服务器的IP地址,用户必须知道代理的存在。

在设计模式中的普通代理和强制代理也是类似的一种结构。
普通代理:我们要知道代理的存在,然后才能访问。
强制代理:调用者直接调用真是角色,而不用关心代理是否存在,其代理的产生是由真是角色决定。

普通代理的UML类图如下所示:

普通代理.jpg

代码示例如下:

//玩家接口
public interface IGamePlayer{
    //登录游戏
    public void login(String name,String password);
    //杀怪
    public void killBoss();
    //升级
    public void upGrade();
}
//普通代理的玩家
public class GamePlayer implements IGamePlayer{
    private String name = "";
    //构造函数限制谁能创建对象,并同时传递姓名
    public GamePlayer(IGamePlayer iGamePlayer,String name) throws Exception{
        if(iGamePlayer==null){
            throw new Exception("不能创建真实角色!");
        }else{
            this.name = name;
        }
    } 
    //打怪
    public void kiilBoss(){
        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 GamePlayerProxy implements IGamePlayer{
    private IGamePlayer iGamePlayer = null;
    //通过构造函数传递要对谁进行代练
    public GamePlayerProxy(String name){
        try{
            gamePlayer = new GamePlayer(this,name);
        }cathch(Exception e){
            //异常处理
        }
    }
    //代练杀怪
    public void killBoss(){
        this.gamePlayer.killBoss();
    }
    //代练登录
    public void login(String name , String password){
        this.gamePlayer.login(user,password);
    }
    //代练升级
    public void upGrade(){
        this.gamePlayer.upGrade();
    }
}
//普通代理的场景类
public class Client{
    public static void main(String[] args){
        //定义一个代练
        IGamePlayer proxy = new GamePlayerProxy("张三");
        //开始打游戏
        System.out.println("开始时间是:2017-4-20  10:45");
        proxy.login("zhangSan","password");
        //开始杀怪
        proxy.killBoss();
        //升级
        proxy.upGrade();
        //记录结束游戏时间
        System.out.println("结束时间是:2017-4-21  058:34");
    }
}

强制代理的UML类图如下所示:

强制代理.jpg

强制代理的示例代码如下:

//强制代理的接口类
public interface IGamePlayer{
    //登录游戏
    public void login(String name,String password);
    //杀怪
    public void killBoss();
    //升级
    public void upGrade();
    //每个人都可以找一下自己的代理
    public IGamePlayer getProxy();
}
//强制代理的真实角色
public class GamePlayer implements IGamePlayer{
    private String name = "";
    private IGamePlayer proxy = null;

    public GamePlayer(String name){
        this.name = name;
    }
    //找到自己的代理
    public IGamePlayer getProxy(){
        this.proxy = new GamePlayerProxy(this);
        return this.proxy;
    }
    //打怪
    public void kiilBoss(){
        if(this.isProxy()){
            System.out.println(this.name+"在打怪!");
        }else{
            System.out.println("请使用指定的代理访问!");
        }
    }
    //登录游戏
    public void login(String user , String password){
        if(this.isProxy()){
            System.out.println("用户名为"user+"的用户"this.name+"登陆成功!");
        }else{
            System.out.println("请使用指定的代理访问!");
        }
    }
    //升级
    public void upGrade(){
        if(this.isProxy()){
            System.out.println(this.name+"又升了一级!");
        }else{
            System.out.println("请使用指定的代理访问!");
        }
    }
    //校验是否是代理访问
    private boolean isProxy(){
        if(this.proxy == null){
            return false;
        }else{
            return true;
        }
    }
}
//强制代理的代理类
public class GamePlayerProxy implements IGamePlayer{
    private IGamePlayer iGamePlayer = null;
    //通过构造函数传递要对谁进行代练
    public GamePlayerProxy(IGamePlayer iGamePlayer){
        this.iGamePlayer = iGamePlayer;
    }
    //代练杀怪
    public void killBoss(){
        this.gamePlayer.killBoss();
    }
    //代练登录
    public void login(String name , String password){
        this.gamePlayer.login(user,password);
    }
    //代练升级
    public void upGrade(){
        this.gamePlayer.upGrade();
    }
    //代理的代理暂时没有
    public IGamePlayer getProxy(){
        return this;
    }
}
//直接访问真实角色
public class Client{
    public static void main(String[] args){
        //定义一个游戏的角色
        IGamePlayer player = new GamePlayer("张三");
        //开始打游戏
        System.out.println("开始时间是:2017-4-20  10:45");
        player.login("zhangSan","password");
        //开始杀怪
        player.killBoss();
        //升级
        player.upGrade();
        //记录结束游戏时间
        System.out.println("结束时间是:2017-4-21  058:34");
    }
}
//直接访问代理类
public class Client{
    public static void main(String[] args){
        //定义一个游戏的角色
        IGamePlayer player = new GamePlayer("张三");
        //定义一个代练
        IGamePlayer proxy = new GamePlayerProxy(player);
        //开始打游戏
        System.out.println("开始时间是:2017-4-20  10:45");
        proxy.login("zhangSan","password");
        //开始杀怪
        proxy.killBoss();
        //升级
        proxy.upGrade();
        //记录结束游戏时间
        System.out.println("结束时间是:2017-4-21  058:34");
    }
}
//强制代理的场景类
public class Client{
    public static void main(String[] args){
        //定义一个游戏的角色
        IGamePlayer player = new GamePlayer("张三");
        //获取指定的代理
        IGamePlayer proxy = player.getProxy();
        //开始打游戏
        System.out.println("开始时间是:2017-4-20  10:45");
        proxy.login("zhangSan","password");
        //开始杀怪
        proxy.killBoss();
        //升级
        proxy.upGrade();
        //记录结束游戏时间
        System.out.println("结束时间是:2017-4-21  058:34");
    }
}
2.有个性的代理

一个类可以实现多个接口,完成不同人物的整合。代理类不仅仅可以实现主题接口,也可以实现其他接口完成不同的任务,而且代理的目的是在目标对象方法的基础上做增强(对目标对象的方法进行拦截和过滤)。

UNL类图如下所示:

代理的个性.jpg

示例代码如下:

//代理类的接口
public interface IProxy{
    //计算费用
    public void count();
}
//代理类
public class GamePlayerProxy implements IGamePlayer,IProxy{
    private IGamePlayer iGamePlayer = null;
    //通过构造函数传递要对谁进行代练
    public GamePlayerProxy(IGamePlayer iGamePlayer){
        this.iGamePlayer = iGamePlayer;
    }
    //代练杀怪
    public void killBoss(){
        this.gamePlayer.killBoss();
    }
    //代练登录
    public void login(String name , String password){
        this.gamePlayer.login(user,password);
    }
    //代练升级
    public void upGrade(){
        this.gamePlayer.upGrade();
    }
    //代理的代理暂时没有
    public void count(){
        System.out.println("");
    }
}
//玩家接口
public interface IGamePlayer{
    //登录游戏
    public void login(String name,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 kiilBoss(){
        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 Client{
    public static void main(String[] args){
        //定义一个玩家
        IGamePlayer player = new GamePlayer("张三");
        //定义一个代练
        IGamePlayer proxy = new GamePlayerProxy(player);
        //开始打游戏
        System.out.println("开始时间是:2017-4-20  10:45");
        proxy.login("zhangSan","password");
        //开始杀怪
        proxy.killBoss();
        //升级
        proxy.upGrade();
        //记录结束游戏时间
        System.out.println("结束时间是:2017-4-21  058:34");
    }
}
3.动态代理

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

动态代理的UML图示如下所示:

动态代理.jpg

上图中的InvocationHandler是JDK提供的动态代理接口,对被代理类的方法进行代理。

示例代码如下所示:

//抽象主题
public interface Subject{
    //业务操作
    public void doSomething(String str);
}
//真实主题
public class RealSubject implements Subject{
    //业务操作
    public void doSomething(String str){
        System.out.println("do  something!-->"+str);
    }
}
//动态代理的Handler类
public class MyInvocationHandler implements InvocationHandler{
    //被代理的对象
    private Object target = null;
    //通过构造函数传递一个对象
    public MyInvocationHandler(Object obj){
        this.target = obj;
    }
    //代理方法
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
        //执行被代理的方法
        return method.invoke(this.target,args);
    }
}
//动态代理类
public class DynamicProxy<T>{
    public static<T> T newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h){
        //寻找JoinPoint连接点,AOP框架使用元数据定义
        if(true){
            //执行一个前置通知
            (new BeforeAdvice()).exec();
        }
        //执行目标,并返回结果
        return (T)Proxy.newProxyInstance(loader,interfaces,h);
    }
}
//通知接口及实现
public interface IAdvice{
        //通知只有一个方法,执行即可
        public void exec();
}
public class BeforeAdvice implements IAdvice{
    public void exec(){
        System.out.println("我是前置通知,我被执行了!");
    }
}
//场景类
public class Client{
    public static void main(String[] args){
        //定义一个主题
        Subject subject = new RealSubject();
        //定义一个Handler
        InvocationHandler handler = new MyInvocationHandler(subject);
        //定义主题的代理
        Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(),
            subject.getClass().getInterfaces(),
            handler);
        //代理的行为
        proxy.doSomething("Finish");
    }
}
//具体业务的动态代理
public class SubjectDynamicProxy extends DynamicProxy{
    public static<T> newProxyInstance(Subject subject){
        //获得ClassLoader
        ClassLoader loader = subject.getClass().getClassLoader();
        //获得接口数组
        Class<?>[] classes = subject.getClass().getInterfaces();
        //获得Handler
        InvocationHandler handler = new MyInvocationHandler(subject);
        return newProxyInstance(loader,classes,handler);
    }
}
//场景类
public class Client{
    public static void main(String[] args){
        //定义一个主题
        Subject subject = new RealSubject();
        //定义主题的代理
        Subject proxy = SubjectDynamicProxy.newProxyInstance(subject);
        //代理的行为
        proxy.doSomething("Finish");
    }
}

欢迎大家关注我的微信公众号

我的微信公众号.jpg
上一篇 下一篇

猜你喜欢

热点阅读