本文主要内容:java 的装饰者模式 的 使用场景 ,使用案例 ,具体代码 ,弊端及解决.
一、使用场景: 对一个项目中的某些功能进行二次开发.二次开发的时候,无法获取到源码,无法使用继承前提下,要对已经存在对象上的功能进行增强.
二、使用案例 : 目前有一个汽车的类,有start(),run(),stop()对之前的start()方法进行升级
三、具体代码
汽车的接口
public interface Car {
public void start();
public void run();
public void stop();
}
汽车的类:(没有办法拿到源码,贴出来方便理解)
public final class OldCar implements Car{ //必须有实现的接口,并且装饰者模式只能增强接口里的方法
@Override
public void start() {
System.out.println("控制旧的汽车启动");
}
@Override
public void run() {
System.out.println("控制旧的汽车运行");
}
@Override
public void stop() {
System.out.println("控制旧的汽车停止");
}
}
装饰者模式
public class MyCar implements Car{
Car car;
public MyCar(Car car) {
this.car=car;
}
@Override
public void start() {
System.out.println("检查天气是否良好");
System.out.println("检查路况是否拥堵");
car.start();
}
@Override
public void run() {
car.run();
}
@Override
public void stop() {
car.stop();
}
}
测试的方法:
public class TestCar {
public static void main(String[] args) {
Car car=new MyCar(new OldCar());
car.start();
car.run();
car.stop();
}
}
四、弊端及解决
弊端:如果被实现的接口中的方法过多,装饰类中的方法过多冗余
解决 :动态代理的方式
public class TestCar {
public static void main(String[] args) {
//1param: 固定值: 告诉虚拟机用哪个字节码加载器加载内存中创建出的字节码文件
//2param: 告诉虚拟机内存中正在被创建的字节码文件中应该有哪些方法
//3param: 告诉虚拟机正在被创建的字节码上的各个方法如何处理
Car car=(Car)Proxy.newProxyInstance(TestCar.class.getClassLoader(), OldCar.class.getInterfaces(),new InvocationHandler() {
//method:代表正在执行的方法
//args:代表正在执行的方法中的参数
//Object:代表方法执行完毕之后的返回值
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代表每个方法执行完毕之后返回对象
Object obj=null;
//判断需要增强的方法
if(method.getName().equalsIgnoreCase("start")){
System.out.println("检查天气是否良好");
method.invoke(new OldgleCar(), args);
System.out.println("检查路况是否拥堵");
}
}
});
car.start();
car.run();
car.stop();
}
}