设计模式之——IOC

IOC即Inversion of control,控制反转的意思,是程序解耦的一种设计原则,核心思想是依赖容器注入对象的引用,依赖注入则是这种设计的具体实现方式,从语义上来说这两个还不能算一样。但从控制反转顾名思义是对控制的反转,那控制的又是什么呢?我们应该知道控制的是对象,想到对象,我们应该会想到工厂,工厂是用来就是生成对象的地方,有人说IOC就是工厂模式的升级,其实我感觉只能说的他们的原理很像,这里就借工厂模式来说一下IOC吧。

先上一段工厂模式的代码吧
代码结构:
代码结构
工厂代码:

//user实体
namespace IOC
{
    public class User
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
}
//实体接口中定义一个方法
namespace IOC
{
    public interface IUser
    {
        void Create(User user);
    }
}
//sqlserver对iuser中create的实现
namespace IOC.SqlServer
{
    class SqlUser : IUser
    {
        public void Create(User user)
        {
            Console.WriteLine("Create user by SqlServer");
        }
    }
}
//oracle的实现
namespace IOC.Oracle
{
    class OraUser : IUser
    {
        public void Create(User user)
        {
            Console.WriteLine("Create user by Oracle");
        }
    }
}
//下面是工厂类,这里可以灵活切换数据库方便扩展
namespace IOC
{
    class Factory
    {
        static readonly string DBName="SqlServer";
        public static IUser Create()
        {
            IUser user;
            switch (DBName)
            {
                case "SqlServer":
                    user = new SqlServer.SqlUser();
                    break;
                default:
                    user = new Oracle.OraUser();
                    break;

            }
            return user;
        }
    }
}
//下面是最终的输出窗口了
namespace IOC
{
    class Program
    {
        static void Main(string[] args)
        {
            User user = new User();
            IUser iu = Factory.Create();
            iu.Create(user);
            Console.ReadLine();
        }        
    }
    
}

工厂方式很好的实现了调用和对象的解耦,我们可以试着以IOC的角度去理解这段代码。谁是容器呢?工厂就是容器,怎么依赖注入呢?其实是容器(也就是工厂)在Main中注入了对SqlServer的依赖,Main中被动的去创建SqlServer对象,那么是不是到这里就完了?答案肯定不是了,如果真是这样还要IOC做什么,直接工厂就是了,上面的实现有个缺点,细心的朋友应该会想,我要是想用换oracle数据库呢?看下面这段代码

static readonly string DBName="SqlServer";
        public static IUser Create()
        {
            IUser user;
            switch (DBName)
            {
                case "SqlServer":
                    user = new SqlServer.SqlUser();
                    break;
                default:
                    user = new Oracle.OraUser();
                    break;

            }
            return user;
        }

如果我换oracle的话是不是得修改DBName?如果我想加mysql的逻辑呢?是不是改的更多,改了工厂类,封闭做的好吗?答案显然易见,这时候我们就需要做出调整,IOC不一样的地方这时候就该显现了。下面总结了三点
一:增加XDataBase.xml

<?xml version="1.0" encoding="utf-8" ?>
<objects>
  <object id="SqlServer" type="IOC.SqlServer.SqlUser"></object>
  <object id="Oracle" type="IOC.Oracle.OraUser"></object>
</objects>

填充容器中实例话的对象集
二:工厂类中实现容器概念

    class 	Container
    {
        Dictionary<string, object> dics = new Dictionary<string, object>();
        public Factory(string fileName){
            InstanceObjects(fileName);
        }
        /// <summary>
        /// 创建容器
        /// </summary>
        /// <param name="fileName"></param>
        public  void InstanceObjects(string fileName)
        {
   			//读取xml文件中的对象集合并加入Dictionary
            XElement xE = XElement.Load(fileName);
            var objs = from obj in xE.Elements("object") select obj;
            dics = objs.ToDictionary(k => k.Attribute("id").Value,
            v =>
            {
                string typeName = v.Attribute("type").Value;
                Type type = Type.GetType(typeName);
                return Activator.CreateInstance(type);
            });            
        }
        /// <summary>
        /// 获取对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public object GetObject(string id)
        {
            object obj = null;
            if(dics.Keys.Contains(id))
            {
                obj = dics[id];
            }
            return obj;
        }
    }

这里利用反射将所用xml中的对象加入Dictionary,同时提供一个获取对象的方法:GetObject,客户端可以根据自己的需要自动切换对象

三:配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!--<add key="TypeName" value="IOC.SqlServer.SqlUser"/>-->
    <add key="TypeName" value="IOC.Oracle.OraUser"/>
    <add key="AssemblyName" value="IOC"/>
  </appSettings>
</configuration>

每次换数据库只需要更改配置文件即可
四:客户端

static readonly string TypeName = ConfigurationManager.AppSettings["TypeName"];
        static void Main(string[] args)
        {
            User user = new User();
            Container 	con= new Container(@"D:\项目\设计模式练习\IOC\IOC\XDataBase.xml");
            IUser iu = (IUser)con.GetObject(TypeName);
            iu.Create(user);
            Console.ReadLine();
        }    

客户端可以根据自己的需要灵活的切换数据库对象,工厂类不需要在做任何修改,如果想再增加Mysql的逻辑,只用新增Mysql类+修改xml文件即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值