通过简单工厂+反射+配置文件实现程序的可扩展

通过简单工厂+反射+配置文件实现程序的可扩展

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>

接下来,我们只需要在后台获取配置文件中的内容,然后根据它实例化对象就行了、

扫描二维码关注公众号,回复: 8646368 查看本文章
//根据配置文件中的内容来创建对象
        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);
        }
发布了19 篇原创文章 · 获赞 6 · 访问量 9425

猜你喜欢

转载自blog.csdn.net/u012712556/article/details/91489210