java方法增强的三种方式

在实际开发中,我们往往需要对某些方法进行增强,常用的方法增强的方式有三种,下面就简单介绍一下三种方式的使用以及特点
需求:
有一个Animal接口,提供了抽象方法eat(),有一个猫类实现了Animal接口,重写了eat方法
 

class Animal {
    public void eat();
}
class Cat implements Animal{
    @Override
    public void eat() {
        System.out.println("吃老鼠");
    }
}
class Test {
    public static void main(String[] args) {
        handleMouse(new Cat());
    }
    public static handleMouse(Animal animal) {
        animal.eat();
    }
}

运行程序:
 

吃老鼠


要求对Cat类中eat方法进行增强(吃老鼠之前抓老鼠)
1.解决方案一:继承
新建一个类SuperCat继承Cat,对eat方法进行重写
 

class SuperCat extends Cat {
    @Override    
    public void eat(){
        System.out.println("抓老鼠");
        super.eat();
    }
}
//测试
class Test {
    public static void main(String[] args) {
        handleMouse(new SuperCat());
    }
    public static handleMouse(Animal animal) {
        animal.eat();
    }
}

运行程序:
 

抓老鼠
吃老鼠

这种方法的前提是能够控制被增强方法的类的构造,而在面向接口编程中, 往往不能明确实现类,比如jdbc连接池需要对Connection的close方法进行增强,将关闭连接改为归还连接,而Connection的实现类并不能确定(由各厂商提供),所以继承的方式不能满足这种需求

2.解决方案二:装饰者设计模式
新建一个类SuperCat实现Animal接口,将animal作为其一个成员属性,对eat方法进行重写
 

public class SuperCat implements Animal {
    Animal animal;
    public SuperCat(Animal animal) {
        this.animal = animal;
    }
    @Override
    public void eat() {
        System.out.println("抓老鼠");
        animal.eat();
    }
}
//测试
public class Test {
    public static void main(String[] args) {
        handleMouse(new SuperCat(new Cat()));
    }
    public static handleMouse(Animal animal) {
        animal.eat();
    }
}

运行程序:
 

抓老鼠
吃老鼠

这种方法要求装饰类与被装饰类要实现同一个接口,如果接口的方法比较多,而只需要对其中一个方法进行增强,则接口中的其他方法需要提供空实现,常用的一个解决方案是定义一个类实现该接口,并提供所有方法的空实现,装饰类若要增强其中一个方法只需继承这个空实现类,并重写相应的方法,如可以对上面解决方案进行改写
 

//定义一个Animal的空实现类
public class AnimalWrapper implement Animal{
    Animal animal;
    public AnimalWrapper(Animal animal) {
        this.animal = animal;
    }
    public void eat() {
    }
}
//定义SuperCat类
public class extends AnimalWrapper{
    public AnimalWrapper(Animal animal) {
        super(animal);
    }
    public void eat() {
        System.out.println("抓老鼠");
        animal.eat():
    }
}

经典应用场景:web开发中,需要对HttpServletRequest的getParameter(String args)方法进行增强(处理get方式乱码),HttpServletRequest提供了一个HttpServletRequestWrapper类,我们可以继承这个空实现类对getParameter(String args)进行增强
3.解决方案三:动态代理
 

public class Test {
     public static void main(String[] args) {
         Cat cat = new Cat();
         Animal proxyInstance = (Animal)Proxy.newProxyInstance(cat.getClass().getClassLoader(), cat.getClass().getInterfaces(), new InvocationHandler() {
                //每次调用代理对象的任意方法,invoke方法就执行了
              @Override
              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                  //需要增强的方法
                  if("eat".equals(method.getName())) {
                       System.out.println("抓老鼠");
                       method.invoke(cat);
                       return null;
                  }
                  //不需要增强的方法
                  return method.invoke(cat);
              }        
         });
         handleMouse(proxyInstance);
     }
     public static void handleMouse(Animal animal) {
         animal.eat();
     }
}

运行程序:
 

抓老鼠
吃老鼠


这种方式比较灵活,只需要被代理类有实现的接口就行

猜你喜欢

转载自blog.csdn.net/qq_38634814/article/details/81712432