public class IocContainer {
static{
registerInstance(Hero.class);
registerInstance(AK47.class);
registerInstance(AK47Bullet.class);
registerInstance(Crystal.class);
registerInstance(GodShield.class);
}
public static void registerInstance(Class<?> clazz){
/**
* Register all the classes to your container
*/
}
public static <T> T inject(Class<?> clazz){
/**
* Return the instance of the demanded class object,
* throw an exception if any classes on the dependency chain is not registered.
*/
return null;
}
public static void main(String[] argv){
Hero hero = IocContainer.inject(Hero.class);
System.out.println(hero.getInfo());
}
}
訓練目的:拓樸排序、圖論、依賴注入、Reflection 技術
請先下點功夫,準備好所有材料,依序創建以下類別及程式
創造抽象Hero, Weapon, Armor, Bullet, Material 介面
再創建其子類別
可以看出,每個建構子中的參數都是依賴於抽象介面型態,才能進行依賴注入 依賴鏈如下圖
要產生一個MyHero實例,就必須先創建出Weapon和Armor的實例, 而我們就必須定義各個抽象參數的實例為何種型態,進行依賴注入。 例如:欲注入的Weapon, Armor型態為 AK47, GodShield 而AK47的建構子又有Bullet和Material,須再先創造此兩實例,以此類推。
而因此我們需要一個容器,來供使用者註冊他的實例型態, 未來需要更換實例型態時,只需要改變此容器即可。
可以看見我們註冊了,MyHero, AK47, AK47Bullet, Crystal, GodShield, 這代表未來若有建構子需要進行依賴注入,則注入了實例型態會參考於此。
Main
函數中只有兩行, 第一行呼叫IOC框架,並令他注入Hero實例到hero物件中, IOC框架會到註冊表中尋找一個已被註冊的Hero的子類別, 因此最後回傳的實例會是MyHero型態。其餘無指出的細節自由設計,如:例外處理。 最後
System.out.println(hero.getInfo());
應會印出要練習(濫用)拓樸排序的話看這
由於,這種依賴鏈,不可能出現有向環狀的情況(如圖), 因此可以套用拓樸排序演算法:
在註冊完成後,建構出一個有向圖, 使用拓樸排序將依賴鏈(全序集)創建出來
AK47Bullet -> Crystal -> AK47 -> GodShield -> MyHero
這個全序依賴鏈建立出來之後,就能夠很簡單的利用以下步驟進行依賴注入:
AK47Bullet -> Crystal -> AK47 -> GodShield -> MyHero