设计模式--继承、装饰者、动态代理

Spring-静态代理、动态代理

我们先来做一个小案例:

案例结构

//建立一个Man类
public interface Man {
    public void run();
}`

//创建一个CommonMan 类实现Man接口
public class CommonMan implements Man {

    public void run() {
        System.out.println("跑步。。。");
    }
}
//测试
public class ManTest {
    public static void main(String[] args) {
        Man man = new CommonMan();
        man.run();
    }
}
//输出结果
/*跑步。。。*/

这是一个简单的通过实现类实现接口的方法,但是现在有一个问题,如果现在有人觉得这个run方法实在是太慢了想要增强这个方法怎么实现?
最简单最的方式是在写一个类继承这个CommonMan 的run方法
方案一:继承

//继承方式,增强CommonMan 的run方法
public class SuperMan extends CommonMan {
    @Override
    public void run() {
        super.run();  //原来的功能没有改变
        System.out.println("跑着跑着飞起来了。。。"); //在原有功能的基础上增强
    }
}

//测试类中需要修改--直接调用SuperMan中的方法
public class ManTest {
    public static void main(String[] args) {
  		//Man man = new CommonMan();
        //man.run();
        SuperMan man = new SuperMan();
        man.run();
    }
}

//输出结果
/*跑步。。。
飞起来。。。*/

方案二:装饰者模式:在不惊动原始设计的基础上,增强某些方法

//装饰者设计模式--增强CommonMan 的run方法
public class SuperMan2 implements Man {
	//这里直接创CommonMan 的父类对象增加复用性
    private Man cm;
    public SuperMan2(Man cm) {
        this.cm = cm;
    }
   
    @Override
    public void run() {
        cm.run();
        System.out.println("跑着跑着飞起来了。。。");
    }
}


//测试类中需要修改--直接调用SuperMan中的方法
public class ManTest {
    public static void main(String[] args) {
		Man m1 = new CommonMan();
        Man m2 = new SuperMan2(m1);
        m2.run();
    }
}

//输出结果
/*跑步。。。
飞起来。。。*/

方案三:动态代理–JDK

//动态代理--JDK
public class ManTest {
        //动态代理
        // Object 代理对象=Proxy.newProxyInstance(被代理对象的类加载器, 被代理对象的接口,实际的增强);
        //创建被代理对象()
        Man m1 = new CommonMan();
        ClassLoader classLoader = m1.getClass().getClassLoader();
        Class[] interfaces = m1.getClass().getInterfaces();
        //创建代理对象
        Man m2 = (Man) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("前置增强代码...");
                Object obj = method.invoke(m1, args);
                System.out.println("后置增强代码...");
                return obj;
            }
        });
        //调用代理对象的方法测试
        m2.run();
    }
}

方案四:动态代理-CGLIB

public class ManTest {
Man m1 = new CommonMan(); //创建目标对象
Enhancer enhancer = new Enhancer();   //创建增强器
enhancer.setSuperclass(m1.class); //设置父类
enhancer.setCallback(new MethodInterceptor() { //设置回调
    @Override
    public Object intercept(Object o, Method method, Object[] args, 
                            MethodProxy methodProxy) throws Throwable {
                            
        System.out.println("前置代码增强....");
        //通过调用父类方法实现对原始方法的调用
        Object obj= method.invoke(o, args);
        //后置增强内容,与JDKProxy区别:JDKProxy仅对接口方法做增强,cglib对所有方法做增强,包括Object 类中的方法
        System.out.println("后置代码增强....");
        return obj;
    }
});

//创建代理对象
Man m2= (Man) enhancer.create();
//调用方法
m2.method();
}

总结

这些方法的统一目标是:对一个类的一个方法不满意,所以要增强这个类的这个方法

方案一

:继承,重写该方法
优点:简单
缺点:继承只能单一继承,而且继承是需要必须重写被继承类的所有方法

方案二

:装饰者设计模式
优点:解决了继承的缺点
缺点:相对比较麻烦,在测试的时候需要先创建原来的类(CommonMan)对象作为参数,在创建一个增强的类(SuperMan2)对象对CommonMan对象进行包装增强,这样层级太多,浪费资源。

方案三

:动态代理
1. JDK的动态代理(JDK自带的)
优点:解决了层数太多,浪费资源的情况
缺点:稍有难度,必须有接口
注意:代理对象和被代理对象之间是兄弟关系
2. CgLib的动态代理(第三方的)
优点:不需要接口
缺点:需要导入jar包
注意:代理对象和被代理对象是父子关系

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值