【Java反射機制】用反射改進簡單工廠模式設計

  若是作開發的工做,工廠設計模式大概都已經深刻人心了,比較常見的例子就是在代碼中實現數據庫操做類,考慮到後期可能會有數據庫類型變換或者遷移,通常都會對一個數據庫的操做類抽象出來一個接口,而後用工廠去獲取實際數據庫操做類實例。數據庫

  下面舉一個最簡單的工廠模式例子:設計模式

interface IAnimal {
    void talk();
}
class Cat implements IAnimal {
    @Override
    public void talk() {
        System.out.println("I'm cat");
    }
}
class Dog implements IAnimal {
    @Override
    public void talk() {
        System.out.println("I'm dog");
    }
}
class AnimalFactory {
    private AnimalFactory() {}
    public static IAnimal getInstance(String animal) {
        if ("Cat".equals(animal)) {
            return new Cat();
        } else if ("Dog".equals(animal)) {
            return new Dog();
        } else {
            return null;
        }
    }
}
public class Main {
    public static void main(String[] args) throws ParseException{
        IAnimal animal = AnimalFactory.getInstance("Cat");
        animal.talk();
        animal = AnimalFactory.getInstance("Dog");
        animal.talk();
    }
}
View Code

  最簡潔的例子了, 客戶端首先想要生成一個Cat的實例,傳入「Cat」,一陣操做以後,又想生成Dog實例,直接傳入「Dog」到工廠裏面拿,接着繼續使用。ide

 

  觀察工廠類,裏面是根據客戶端傳過來的字符串手動new一個實例並返回,那若是這個工廠恰好要容納好幾百種實例的返回,並可能會不定時添加新的實例類型,那豈不是每次都要去修改工廠類,有沒有一個辦法我寫一次工廠類,而後工廠類能自動產生並返回客戶端須要的實例? 這個時候咱們能夠利用反射的機制,根據客戶端傳進來的字符串,運用反射原理去尋找咱們所要的實體類。首先呢,接口和實體類都要寫還給他的,接着呢修改工廠類以下:函數

class AnimalFactory {
    private AnimalFactory() {}
    public static IAnimal getInstance(String animal) {
        try {
            Class cls = Class.forName(animal);
            return (IAnimal) cls.newInstance();
        } catch (Exception e) {
            return null;
        }
    }
}
View Code

首先由Class類型的靜態方法forName(String className)找到這個類並返回這個類的Class類型對象, 此時找不到的話會拋出ClassNotFoundException,拋出異常了就返回null咯。this

而後用Class對象的newInstance()方法產生一個實例,這個實例就是forName函數找到的實體類實例。至關於用默認構造函數產生一個實例,因此此處也會拋出異常,好比默認構造函數是私有類型的狀況下。spa

接着,若是我產生的實例都須要根據傳入的參數對應去實例化呢,這個時候,咱們能夠利用反射去找有相應參數的構造函數,再生成一個實例就好啦。設計

interface IAnimal {
    void talk();
}
class Cat implements IAnimal {
    private String name;
    public Cat(String name) {
        this.name = name;
    }
    @Override
    public void talk() {
        System.out.println("I'm cat:" + this.name);
    }
}
class Dog implements IAnimal {
    private String name;
    public Dog(String name) {
        this.name = name;
    }
    @Override
    public void talk() {
        System.out.println("I'm dog:" + this.name);
    }
}
class AnimalFactory {
    private AnimalFactory() {}
    public static IAnimal getInstance(String animal, String name) {
        try {
            Class cls = Class.forName(animal);
            Constructor<?> con = cls.getConstructor(String.class);
            return (IAnimal)con.newInstance(name);
        } catch (Exception e) {
            return null;
        }
    }
}
public class Main {
    public static void main(String[] args) throws ParseException{
        IAnimal animal = AnimalFactory.getInstance("Cat", "Miao");
        animal.talk();
        animal = AnimalFactory.getInstance("Dog", "Wang");
        animal.talk();
    }
}
View Code

在工廠類中,咱們若是找到這個類的Class類型對象時,就用這個Class對象去找對應的Constructor對象,getConstructor方法接受無數個參數,根據須要指定咱們要找的這個構造函數參數類型是什麼,例子中這個類型是String,因此咱們用String.class去指定這個類型即是String類型,接着用這個Constructor對象,newInstance(String para)實例化並返回。code

 

至此,用反射改進傳統工廠模式步驟完成。 若有寫的不妥之處,歡迎之處斧正。對象

 

 

尊重知識產權,轉載引用請通知做者並註明出處!blog

相關文章
相關標籤/搜索