您的位置:首页 > 编程语言 > Java开发

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:动态代理的主要意图就是横切面编程,在不改变我们已有的代码结构的情况下增强或控制对象的行为
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息