若是作開發的工做,工廠設計模式大概都已經深刻人心了,比較常見的例子就是在代碼中實現數據庫操做類,考慮到後期可能會有數據庫類型變換或者遷移,通常都會對一個數據庫的操做類抽象出來一個接口,而後用工廠去獲取實際數據庫操做類實例。數據庫
下面舉一個最簡單的工廠模式例子:設計模式
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(); } }
最簡潔的例子了, 客戶端首先想要生成一個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; } } }
首先由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(); } }
在工廠類中,咱們若是找到這個類的Class類型對象時,就用這個Class對象去找對應的Constructor對象,getConstructor方法接受無數個參數,根據須要指定咱們要找的這個構造函數參數類型是什麼,例子中這個類型是String,因此咱們用String.class去指定這個類型即是String類型,接着用這個Constructor對象,newInstance(String para)實例化並返回。code
至此,用反射改進傳統工廠模式步驟完成。 若有寫的不妥之處,歡迎之處斧正。對象
尊重知識產權,轉載引用請通知做者並註明出處!blog