天天看點

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();
     }
}
           

運作程式:

抓老鼠
吃老鼠
           

這種方式比較靈活,隻需要被代理類有實作的接口就行