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

概要:

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值