JAVA的23种设计模式---代理模式(二)
2017-05-20 10:47
363 查看
概要:
该文章参考了《设计模式之禅》一书及一些前辈的博客文章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 cl ed21 ass 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:动态代理的主要意图就是横切面编程,在不改变我们已有的代码结构的情况下增强或控制对象的行为
相关文章推荐
- 【结构型模式】代理模式(Proxy)之23种java设计模式
- Java开发中的23种设计模式详解----代理模式(Proxy)
- Java23种设计模式详解1——代理模式
- Java23种设计模式之-----代理模式
- java23种设计模式 代理模式(五)
- java23种设计模式--代理模式(proxy)
- Java23种设计模式——代理模式
- Java 23种设计模式之代理模式
- java 23种常用设计模式之代理模式(Proxy)
- Java 23种设计模式之代理模式
- JAVA的23种设计模式---代理模式(一)
- Java开发中的23种设计模式之八:代理模式(Proxy)
- 走穿java23种设计模式-6代理模式
- Java23种设计模式案例:代理模式(Proxy)
- 重学java23种设计模式(12)代理模式
- java23种设计模式之代理模式
- java_23种设计模式之代理模式
- Java经典23种设计模式之结构型模式(三)------附代理模式、适配器模式、外观模式区别
- 追MM与Java的23种设计模式
- 追MM与Java的23种设计模式