设计模式之禅笔记7--代理模式

代理模式

定义:为其他对象提供一种代理以控制对这个对象的访问。
角色如下:
1. Subject抽象主题角色
2. RealSubject具体主题角色。也叫做被委托角色。
3. Proxy代理主题角色。也叫做代理类,委托类。

public interface Subject {

    //定义一个方法
    public void  request();
}
public class RealSubject implemnts Subject{
    //实现方法
    public void request(){
        //业务处理
    }
}
public class Proxy implements Subject{
    //要代理哪个实现类
    private Subejct subejct = null;
    //默认被代理者
    public Proxy(){
        this.subject = new proxy();
    }
    //通过构造函数传递代理者
    public Proxy(Object...objects){

    }
    public proxy(Subject subject){
        this.subejct = subject;
    }
    //实现接口中定义的方法
    public void request(){
        this.before();
        this.subject.request();
        this.after();
    }
    public void before(){do Something}
    public void after(){do Something}
}

优点:
1. 职责清晰
2. 高扩展性
3. 智能化

普通代理:客户端只能访问代理角色,而不能访问真实角色。
强制代理:一般的思维是要通过代理找到真实的角色。但是强制代理是通过真实角色找到代理角色。否则你不能访问。即先new出一个真实角色,再通过真实角色的getProsy()方法得到代理角色。客户端再调用代理角色的方法。

代理是有个性的:代理类不仅仅可以实现主题接口,也可以实现其他接口完成不同的任务。代理的目的就是在目标对象方法的基础上增强,其本质是对目标对象方法进行拦截和过滤。

动态代理

在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。相对来说,自己写代理类就是静态代理。以打游戏为例。其中InvocationHandler是JDK提供的动态代理接口,对被代理类的方法进行处理。

//动态代理类
public class GamePlayIH implements InvocationHandler{
    //被代理者
    Class cls = null;
    //被代理的实例
    Object obj = null;
    //我要代理谁
    public GamePlayIH(Object _obj){
        this.obj = _obj;
    }
    //调用被代理类的方法
    public Object invoke(Object proxy,Method method,Object[] args){
        Object result = mehtod.invoke(this.obj,args);
        return result;
    }
}

invoke方法是接口InvocationHandler定义必须实现的。他完成对真实方法的调用。

public class Client{
    public static void main(String[] args) throws Throwable{
        //定义一个痴迷的玩家
        IGamePlayer player = new GamePlayer("张三");
        //定义个Handler
        InvocationHandler handler = new GamePlayIH(player);
        //开始打游戏
        System.out.println("开始时间是:2009-8-25 10:45");
        //获得类的Class loader
        ClassLoader cl = player.getClass().getClassLoader();
        //动态产生一个代理者
        IGamePalyer proxy = (IGamePalyer )Proxy.newProxyInstance(cl,new Class[]{IGamePalyer.class},handler);
        //登录
        proxy.login("zhngshan","password");
        proxy.killBoss();
        proxy.upgrade();
        System.out.println("游戏时间结束");
    }
}

动态代理的通用源码:

public interface Subject {
    public void doSomething(String abc);
}
public class RealSubject implements Subject {

    //业务操作
    public void doSomething(String str) {
        System.out.println("do something!---->" + str);
    }

}
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){
        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 AfterAdvice implements IAdvice {

    public void exec() {
        System.out.println("我是后置通知,我被执行了");
    }

}
public class Client {

    public static void main(String[] args) {
        Subject subject = new RealSubject();

        Subject proxy = SubjectDynamicProxy.newProxyInstance(subject);

        proxy.doSomething("Finish");
    }
}

一个类的动态代理是这样的,由InvocationHandler的实现类实现所有的方法,由其invoke方法接管所有方法的实现,其调用过程如下图:
这里写图片描述
以上的Dynamicproxy类不具有业务意义,是一个通用类。可以增加一个具有业务的动态代理:

public class SubejctDynamicProxy extends DynamicProxy{
    public static <T> T newProxyInstance(Subject subject){
        ClassLoader loader = subject.getClass().getClassLoader();
        Class<?> calsses = subejct.getClass().geInterfaces();
        InvocationHandler handler = new MyInvocationHandler(subject);
        return newProxyInstance(loader,classes,handller);
    }
}

注:要实现动态代理的首要条件:被代理类必须实现一个接口。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值