设计模式—代理设计模式

代理设计模式

设计模式其实就是如何去合理的进行抽象。

优点:保护真实对象,让 其职能更明确,有扩展性

相关概念:真实对象(老板)      代理对象(秘书)       抽象对象:谈生意,吃饭(抽象功能)

1、静态代理

由代理对象代理所有真实对象的功能,需要自己编写代理类,每个代理的功能需要单独去编写

缺点:代理真实对象的功能比较多时,对应的方法需要编写很多。

光说没用,上代码!

A、建立抽象对象实现抽象功能(功能接口)

里边有两个抽象方法,吃饭和谈生意。

package pojo;

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 22:03
 * @Description:
 */
public interface Gongneng {
    void chifan();
    void tanshengyi();
}

B、建立真实对象(Boss类)实现Gongneng接口,一个name属性,两个重写的方法,输出控制台语句,非常简单。

package pojo;

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 21:59
 * @Description:
 */
public class Boss implements Gongneng {
    private String name;

    public void setName(String name){
        this.name=name;
    }

    public String getName(){
        return name;
    }

    public Boss() {
    }

    public Boss(String name) {
        this.name = name;
    }

    @Override
    public void chifan() {
        System.out.println("共进晚餐");
    }

    @Override
    public void tanshengyi() {
        System.out.println("谈个十个亿的小生意");
    }

}

C、建立代理类(Mishu类)  秘书类同样去实现Gongneng接口,重写两个抽象方法。

package pojo;

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 22:04
 * @Description:
 */
public class Mishu implements Gongneng {
    private Boss boss = new Boss("大老板");
    @Override
    public void chifan() {
        System.out.println("先预约下时间吧");
        boss.chifan();
        System.out.println("登记在册");
    }

    @Override
    public void tanshengyi() {
        System.out.println("先预约下时间吧");
        boss.tanshengyi();
        System.out.println("登记在册");
    }
}

D、建立访问对象(我)  测试类看下结果

package pojo;

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 22:06
 * @Description:
 */
public class Wo {
    public static void main(String[] args){
        Mishu mishu =  new Mishu();
        mishu.chifan();
    }
}

 E、结果

 

总结:上边是很简单的代码,很明显有了秘书这个代理类,保护了真实对象大老板,使大老板的职责更加明确,专注于大事。

同样,秘书代理类也实现了扩展的功能,例如:要预约时间、登记在册。 

但是,也可以看出,真实对象中每增加一个功能,代理对象都得去再实现一次,造成繁琐,所以就显出动态代理的优点。

2、动态代理

为解决静态代理频繁编写代理类中代码的缺点,提供两种方式。

A、JDK动态代理

优点:JDK自带,不用额外导入Jar包

缺点:真实对象必须实现接口,底层运用反射机制效率低下。

使用时可能造成ClassCastException异常:原因是希望把接口对象转换为具体对象。

代码实例:

1、真实对象不变,跟静态相比区别在代理类;

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 21:59
 * @Description:
 */
public class Boss implements Gongneng {

    public void chifan() {
        System.out.println("共进晚餐");
    }

    public void tanshengyi() {
        System.out.println("谈个十个亿的小生意");
    }

}

2、Gongneng接口

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 22:03
 * @Description:
 */
public interface Gongneng {
    void chifan();
    void tanshengyi();
}

3、秘书类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 22:25
 * @Description:
 */
public class Mishu implements InvocationHandler {
    Boss boss = new Boss();

    /**
     * 重写invoke方法,三个参数解释如下
     * @param proxy 真实对象
     * @param method 方法
     * @param args 参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("预约时间");
        //反射使用method调用具体的方法,boss真实对象传入
        Boss result = (Boss) method.invoke(boss, args);
        System.out.println("登记在册");
        return result;
    }
}

4、我 测试类

import java.lang.reflect.Proxy;

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 22:06
 * @Description:
 */
public class Wo {
    public static void main(String[] args){
        Mishu mishu = new Mishu();
        Gongneng gongneng = (Gongneng) Proxy.newProxyInstance(Wo.class.getClassLoader(), new Class[]{Gongneng.class}, mishu);
        gongneng.chifan();
    }
}

5、结果

 

 总结:JDK动态代理的机制是接口调用“谈生意”方法,其实调用的是Proxy代理类,它会自动回调invoke方法,实现接口就可以把Proxy赋给接口。接口.tanshengyi();实际上调Proxy的谈生意,而调Proxy的机制是每次调任意方法之前都要走invoke()方法。这是Java三大特性之一的多态特性。

多态:同一个方法调用,由于对象的不同可能会有不同的行为。而接口毫无疑问可以体现出多态的特性,接口可以多继承,例如超类对象引用 访问 子类对象,类B类C实现接口方法fun();   通过将类B和类C的实例赋给接口引用A,实现方法运行时动态绑定。

反射时用到类加载器加载类,JVM虚拟机只生成一个。

B、CGLIB动态代理

优点:基于字节码,生成真实对象的子类,运行效率高于JDK动态代理,不用实现接口

缺点:非JDK功能,需要导入额外Jar包

1、导包  cglib  asm (字节码解析包)

2、Boss

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 21:59
 * @Description:
 */
public class Boss implements Gongneng {

    public void chifan() {
        System.out.println("共进晚餐");
    }

    public void tanshengyi() {
        System.out.println("谈个十个亿的小生意");
    }

}

3、功能

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 22:03
 * @Description:
 */
public interface Gongneng {
    void chifan();
    void tanshengyi();
}

4、秘书

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 22:25
 * @Description:
 */
public class Mishu implements MethodInterceptor {
    /**
     * 重写intercept方法,四个参数
     * @param o  子类对象
     * @param method  代理的方法
     * @param objects 参数
     * @param methodProxy 子类重写父类的代理方法
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("预约时间");
        //它俩等效   
        //method.invoke(o,objects);  调子类重写的方法
        //调父类
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("登记在册");
        return result;
    }
}

5、测试

import net.sf.cglib.proxy.Enhancer;

import java.lang.reflect.Proxy;

/**
 * @Auther:jiaxuan
 * @Date: 2019/4/2 0002 22:06
 * @Description:
 */
public class Wo {
    public static void main(String[] args){
        Enhancer enhancer = new Enhancer();
        //生成Boss类的子类
        enhancer.setSuperclass(Boss.class);
        //当调Boss类的子类时处理程序为秘书
        enhancer.setCallback(new Mishu());
        //产生老总对象子类
        Boss boss = (Boss) enhancer.create();
        boss.tanshengyi();
    }
}

6、结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值