通過簡單工廠+反射+配置文件實現程序的可擴展

通過簡單工廠+反射+配置文件實現程序的可擴展

1 通過簡單工廠模式實現面向接口編程

假設我們有一下幾個類代表遊戲用不用的角色

//繼承接口類
    public class Human
    {
        //重寫接口類方法
        public void ShowKing()
        {
            Console.WriteLine("The king of {0} is Sky", this.GetType().Name);
        }
    }
   public class NE
    {
        public void ShowKing()
        {
            Console.WriteLine("The king of {0} is Blue", this.GetType().Name);
        }
    }
public class Player
    {
        public int id { set; get; }
        public string name { set; get; }

    }

其中Player是玩家,如果玩家需要使用Human這個遊戲角色, 需要給Player添加如下方法。

public void Play(Human role)
        {
            Console.WriteLine("{0} play games", this.name);
            role.ShowKing();
        }

若他想玩NE這個解釋,就還需要添加一個類似的方法。

public void Play(NErole)
        {
            Console.WriteLine("{0} play games", this.name);
            role.ShowKing();
        }

大家會不會覺得這樣的程序的擴展性太低,經常需要修改,弄有沒有辦法可以一勞永逸呢。沒錯,通過簡單工廠模式能在一定程度上解決這個問題。所謂簡單工廠,實現它的主要方式就是通過傳遞給工廠方法的參數,動態實例化一個對象,爲了實現這個功能,這些對象所屬德類必須繼承於一個公共父類,這樣採用用子類代替父類出現的地方。我們可以用定義一個父類來當做這個公共父類。
我們首先來定義這個接口,需要在這個接口中聲明一個子類都需要用到的方法。

   //種族類都繼承於這接口
   public interface IRace
   {
        //子類會重寫這個方法
        //這樣在用子類代替父類時,會有自己獨特的行爲
        void ShowKing();
   }

接下來我們對遊戲角色

    //繼承於接口後, 可以用子類賴替代父類出現的地方 並且可以使用子類自己的行爲
    public class NE :IRace
    {
        public void ShowKing()
        {
            Console.WriteLine("The king of {0} is Sky", this.GetType().Name);
        }
    }
    //繼承接口類
    public class Human : IRace
    {
        //重寫接口類方法
        public void ShowKing()
        {
            Console.WriteLine("The king of {0} is Sky", this.GetType().Name);
        }
    }

接下來在Play中玩家使用任何角色都可以用同樣的方法了

//將接口作爲參數可以使player面向抽象  依賴倒置
        public void Play(IRace role)
        {
            Console.WriteLine("{0} play games", this.name);
            role.ShowKing();
        }

爲了方便通過傳入的參數來確定要實例化那個角色對象,我們可以使用一個工廠類來實現。

//種族類型的枚舉
    public enum RaceType
    {
        Human,
        NE,
        ORC,
        UnDead
    }

    public class ObjectFactory
    {
        //根據傳遞的種族類型動態地創建Irace的子類
        public static IRace CreateRace(RaceType type)
        {
            IRace race = null;
            switch (type)
            {
                case RaceType.Human:
                    race = new Human(); break;
                case RaceType.NE:
                    race = new NE(); break;
                default:
                    throw new Exception("wrong raceType");
            }
            return race;
        }

    }

然後在Main()方法中調用CreateRace()就能創建一個角色了。

IRace role= ObjectFactory.CreateRace(RaceType.Human);
Player player = new Player()
            {
                id = 1,
                name = "LC"
            };
player.Play(role);

自此時我們就實現了面向接口編程。

通過讀取配置文件中的內容來實例化遊戲角色

先在配置文件中添加要創建的角色對象的信息

<appSettings>
        <add key="IRaceType" value="Human" />
    </appSettings>

接下來,我們只需要在後臺獲取配置文件中的內容,然後根據它實例化對象就行了、

//根據配置文件中的內容來創建對象
        private static string raceTypeConfig = ConfigurationManager.AppSettings["IRaceType"];
        public static IRace CreateRaceByConfig()
        {
            RaceType type = (RaceType)Enum.Parse(typeof(RaceType), raceTypeConfig);
            return CreateRace(type);
        }

最後只需要在Mina()方法中調用CreateRaceByConfig()實例化角色就行了。

再加上反射實現可擴展

當我們想給一個項目添加一個新功能時,可以再新建一個項目,然後舊項目引用新項目的dll,最後再重新編譯一下老項目。其實這樣就很麻煩。還有一種方法就是把新項目的dll文件複製到老項目的bin\Debug下,然後在老項目中通過反射實例化出新項目中的對象。
先在配置文件中添加新項目中對象的信息。

<add key="IRaceTypeReflaction"  value="SimpleFactoryServiceExtend,SimpleFactoryServiceExtend.FIve" />

value中的兩個值分別是dll的名稱和具體類的名稱
然後在工廠方法通過反射中實例化對象就行了

 //根據讀取配置文件的內容通過反射創建文件
        private static string configString = ConfigurationManager.AppSettings["IRaceTypeReflaction"];
        private static string DllName = configString.Split(',')[0];
        private static string ClassName = configString.Split(',')[1];
    
        public static IRace CreateRaceByReflaction()
        {
            //加載指定dll
            Assembly assembly = Assembly.Load(DllName);
            //實例化dll中的一個對象
            Type type = assembly.GetType(ClassName);
            return (IRace)Activator.CreateInstance(type);
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章