JAVA的23种设计模式---代理模式(二)

来源:互联网 发布:乐清市网络问效平台 编辑:程序博客网 时间:2024/05/29 02:18

概要:

该文章参考了《设计模式之禅》一书及一些前辈的博客文章

1.该文章阐述了代理模式的基础原理及示例代码;
2.该文章适合初学设计模式的技术人员研习;
3.该文章有许多不足之处,请各位大咖指正,喷子绕道;
4.该文章是《JAVA的23种设计模式—代理模式(一)》的续写,点此跳转到第一部分

正文:

4.代理模式的多接口实现示例代码:

package com.csdn;/** * 代理扩展方法接口 * @author Administrator * */public interface IProxy {    //代管店铺收取费用方法    public void pay();  }
package com.csdn;/** * 抽象开店 * @author Administrator * */public interface Shop {    //开门营业    public void openTheDoor();    //卖东西    public void sell();    //关门打烊    public void closeTheDoor();}
package com.csdn;/** * 具体的一家店 * @author Administrator * */public class Boss implements Shop {    //店主名字    private String name = "";    //构造器限制谁能创建对象,并同时传递店主名    public Boss(Shop shop,String _name)throws Exception {        if(shop == null){            throw new Exception("不能创建一个店铺");        }else{            this.name = _name;        }    }    //店门打开方法    @Override    public void openTheDoor() {        System.out.println(this.name+"的店门打开了..");    }    //营业、卖东西方法    @Override    public void sell() {        System.out.println(this.name+"的店开始出售东西..");    }    //关门打烊方法    @Override    public void closeTheDoor() {        System.out.println(this.name+"的店门关上了..");    }}
package com.csdn;/** * 代理开店服务 * @author Administrator * */public class BossProxy implements Shop,IProxy{    private Shop boss = null;    //通过构造函数来传递对谁的店进行代理    public BossProxy(String _boss){        try {            boss = new Boss(this, _boss);        } catch (Exception e) {            // TODO: handle exception        }    }    //代理打开店门方法    @Override    public void openTheDoor() {        this.boss.openTheDoor();    }    //代理营业、卖东西方法    @Override    public void sell() {        this.boss.sell();    }    //代理关门打烊方法    @Override    public void closeTheDoor() {        this.boss.closeTheDoor();        this.pay();    }    @Override    public void pay() {        System.out.println("代理收取代管费100元..");    }}
package com.csdn;/** * 模拟代理经营店铺 * @author Administrator * */public class Business {    public static void main(String[] args) {                //“小明”的店铺需要代理服务        Shop proxy = new BossProxy("小明");        //代理打开小明的店门        proxy.openTheDoor();        //代理帮小明卖东西        proxy.sell();        //代理关上小明的店门并向小明收取了管理费        proxy.closeTheDoor();           }}

输出:

小明的店门打开了..小明的店开始出售东西..小明的店门关上了..代理收取代管费100元..

注:
a:该示例与之前相比增加了IProxy接口,增加了pay方法以及其实现,并在closeTheDoor方法中调用了它的实现方法
b:代理的职责并不单一,可以组合其他的真实角色,也可以实现自己的职责,它可以为真实角色预处理消息、过滤消息、消息转发、事后处理消息等功能。

5.通用代理模式模板代码实现:

package com.csdn;/** * 抽象类,可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求 * @author Administrator * */public interface Subject {      //定义一个方法      public void request();  } 
package com.csdn;/** * 具体类,也叫被委托的角色、被代理的角色,它才是最重要的,是业务逻辑的具体执行者。  * @author Administrator * */ public class RealSubject implements Subject {      @Override      public void request() {          //业务逻辑处理      }  } 
package com.csdn;/** * 代理类 * @author Administrator * */ public class Proxy implements Subject {      //要代理哪个实现类      private Subject subject = null;      //默认被代理者      public Proxy() {          this.subject = new Proxy();      }      //通过构造方法传递代理者      public Proxy(Object...objects) {      }      //实现接口中的方法      @Overrdie      public void request() {          this.before();          this.subject.request();          this.after();      }           //预处理      private void before() {          //do something      }           //善后处理      private void after() {          //do something      }  } 

5.虚拟代理模式代码实现:

package com.csdn;/** * 虚拟代理类 * @author Administrator * */ public class Proxy implements Subject {      //要代理哪个实现类      private Subject subject;       //实现接口中的方法      @Overrdie      public void request() {          if(subject == null){            subject = new RealSubject();        }        subject.request();    }        } 

注:在需要的时候才初始化主题对象,可以避免被代理对象较多而引起的初始化缓慢问题

6.动态代理模式代码实现示例代码:

package com.csdn;/** * 抽象开店 * @author Administrator * */public interface Shop {    //开门营业    public void openTheDoor();    //卖东西    public void sell();    //关门打烊    public void closeTheDoor();}
package com.csdn;/** * 具体的一家店 * @author Administrator * */public class Boss implements Shop {    //店主名字    private String name = "";    //带参构造器    public Boss(String _name) {        this.name = _name;    }    //店门打开方法    @Override    public void openTheDoor() {        System.out.println(this.name+"的店门打开了..");    }    //营业、卖东西方法    @Override    public void sell() {        System.out.println(this.name+"的店开始出售东西..");    }    //关门打烊方法    @Override    public void closeTheDoor() {        System.out.println(this.name+"的店门关上了..");    }}
package com.csdn;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/** * 动态代理类 * @author Administrator * */public class DynamicAgent implements InvocationHandler{    //被代理者    Class clazz = null;    //被代理的实例    Object obj = null;    //要代理谁    public DynamicAgent(Object _obj){        this.obj = _obj;    }    //调用被代理的方法    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        Object result = method.invoke(this.obj, args);        //此处可以加入面向切面的功能,AOP(面向切面的编程)的提现处        //如在门被打开时的提醒功能        if(method.getName().equalsIgnoreCase("openTheDoor")){            System.out.println("(有人正在打开店门!)");        }               return result;    }}
package com.csdn;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;/** * 模拟动态代理经营店铺 * @author Administrator * */public class Business {    public static void main(String[] args) {        //初始化“小明”的店铺        Boss boss = new Boss("小明");        //“小明”的店铺需要动态代理服务        InvocationHandler handler = new DynamicAgent(boss);        //获得类的类加载器        ClassLoader cl = boss.getClass().getClassLoader();        //动态产生一个代理者        Shop proxy = (Shop)Proxy.newProxyInstance(cl,new Class[]{Shop.class}, handler);        //代理打开小明的店门        proxy.openTheDoor();        //代理帮小明卖东西        proxy.sell();        //代理关上小明的店门        proxy.closeTheDoor();    }}

输出:

小明的店门打开了..(有人正在打开店门!)小明的店开始出售东西..小明的店门关上了..

注:
a:invoke方法是InvocationHandler定义必须实现的,他完成对真实方法的调用,所有被代理的方法都由InvocationHandler接管实际的处理任务
b:对于日志、事物、权限等都可以在系统设计阶段不用去考虑,而在设计后通过AOP(面向切面的编程)的方式切过去

7.通用动态代理模式模板代码:

package com.csdn;/** * 抽象类 * @author Administrator * */public interface Subject {      //业务操作     public void doSomething(String str);  } 
package com.csdn;/** * 具体类 * @author Administrator * */ public class RealSubject implements Subject {      //业务操作    @Override      public void doSomething(String str){        System.out.println("do something----->" + str);    };   } 
package com.csdn;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;/** * 动态代理的Handler类 * @author Administrator * */public class MyInvocationHandler implements InvocationHandler {    //被代理的对象    private Object target = null;    //通过构造函数传递一个对象    public MyInvocationHandler(Object _obj){        this.target = _obj;    }    //代理方法    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        //执行被代理的方法        return method.invoke(this.target, args);    }}
package com.csdn;import java.lang.reflect.InvocationHandler;/** * 动态代理类 * @author Administrator * * @param <T> */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);            }}
package com.csdn;/** * 通知接口 * @author Administrator * */public interface IAdvice {    //通知的方法    public void exec();}
package com.csdn;/** * 通知实现类 * @author Administrator * */public class BeforeAdvice implements IAdvice {    @Override    public void exec() {        System.out.println("前置通知");    }}
package com.csdn;import java.lang.reflect.InvocationHandler;/** * 动态代理场景类 * @author Administrator * */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");    }}

输出:

前置通知do something----->Finish

注:
a:在动态代理类中newProxyInstance方法有三个参数,其中c.getInterfaces查找该类的所有接口,然后实现接口的所有方法,由new MyInvocationHandler(subject)这个对象接管

扩展:

package com.csdn;import java.lang.reflect.InvocationHandler;/** * 具体业务的动态代理 * @author Administrator * */public class SubjectDynamicProxy extends DynamicProxy{    public static <T> T newProxyInstance(Subject subject){        //获得类加载器        ClassLoader loader = subject.getClass().getClassLoader();        //获得接口数据        Class<?>[] classes = subject.getClass().getInterfaces();        //获得Handler        InvocationHandler handler = new MyInvocationHandler(subject);        return newProxyInstance(loader, classes, handler);    }}
package com.csdn;/** * 动态代理场景类 * @author Administrator * */public class Client {    public static void main(String[] args) {        //定义一个主题        Subject subject = new RealSubject();        //定义主题的代理        Subject proxy = SubjectDynamicProxy.newProxyInstance(subject);        //代理的行为        proxy.doSomething("Finish");    }}

注:
a:动态代理的主要意图就是横切面编程,在不改变我们已有的代码结构的情况下增强或控制对象的行为

原创粉丝点击