依赖倒置原则 个人理解

1.依赖倒置原则:(DIP)高层模块不应依赖底层模块,两者都应依赖抽象。
     为什么依赖注入? 为了实现控制反转.
     为什么控制反转? 我们的软件设计需要符合依赖倒置原则.

2.依赖注入(DI)  控制反转(IOC)(技术手段)

   ·IOC容器,依赖注入,IOC控制反转的关系
        依赖注入,反转依赖的!因为有了依赖注入,才有了控制反转; 
         即先有容器再有依赖注入,最后才有控制反转。

    IOC容器,依赖注入框架的东西提供的。映射依赖、管理对象创建和生命周期;再也不用New,有人帮你new。

场景例子:假设你是一个五岁的小孩,你饿了就要吃,需求。怎么找吃的?
      1.找吃的 直接从冰箱拿
      2.找妈妈要   父母(IOC容器)会给你做食物,然后拿给你(注入)
   从你想吃东西的需求,从主动去冰箱(正转)拿食物,到想吃的食物而被动获得(反转),即妈妈做
   控制反转:组件对象控制权的转移。类型A(小孩)中需要使用类型B(食物),这个B的创建并不由A来负责,而是由第三方(妈妈)创建。
   IOC一种反转流、依赖和接口的方式,他把传统上由程序代码直接操控的对象的调用权交给第三方(容器),通过第三方来实现对象组件的配置和管理。
   

场景:父亲给孩子讲故事,只要给父亲一本书,他就可以照着书给孩子将故事。

  1.不经过任何设计模式和设计原则加工的传统的OOP方式,强依赖,以利于扩展。

namespace FatherStoryCustom
{
    /// <summary>
    /// 场景:父亲给孩子讲故事,只要给父亲一本书,他就可以照着书给孩子将故事。
    /// 
    /// 不经过任何设计模式和设计原则加工的传统的OOP方式。。
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            Father father = new Father();
            father.Read();

            Console.ReadKey();
        }
    }

    public class Book
    {
        public string GetContent()
        {
            return "从前有座山,山上有座庙.....";
        }
    }

    public class Father
    {
        public void Read()
        {
            Book book = new Book();
            Console.WriteLine("爸爸开始讲故事啦..");
            Console.WriteLine(book.GetContent());
        }
    }

}

场景:父亲给孩子讲故事,只要给父亲一本书,他就可以照着书给孩子将故事。

有一天需求变了,不给书了,给报纸,读报纸上的新闻。

2.通过工厂模式来实现,但还是需要在工厂中创建对象

namespace FatherStoryDIP
{
    /// <summary>
    /// 场景:父亲给孩子讲故事,只要给父亲一本书,他就可以照着书给孩子将故事。
    /// 有一天需求变了,不给书了,给报纸,读报纸上的新闻。
    /// 上一个普通做法耦合太强,父亲太依赖书了。
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            // 工厂模式创建对象
            Father father = new Father("Paper");

            Console.ReadKey();
        }
    }

    /// <summary>
    /// 读物的接口
    /// </summary>
    public interface IReader
    {
        string GetContent();
    }

    public class Paper : IReader
    {
        public string GetContent()
        {
            return "王思聪被限制消费..";
        }
    }

    public class Book : IReader
    {
        public string GetContent()
        {
            return "从前有座山,山上有座庙...";
        }
    }

    public class Father
    {
        private IReader _reader { get; set; }
        // 工厂模式创建对象
        public Father(string readerName)
        {
            _reader = ReaderFactory.GetReader(readerName);
        }

        public void Read()
        {
            Console.WriteLine("爸爸给孩子开始讲故事了..");
            Console.WriteLine(_reader.GetContent());
        }
    }
}
namespace FatherStoryDIP
{
    public static class ReaderFactory
    {
        public static IReader GetReader(string readType)
        {
            if (string.IsNullOrEmpty(readType))
            {
                return null;
            }

            switch (readType)
            {
                case "Paper":
                    return new Paper();
                case "Book":
                    return new Book();
                default:
                    return null;
            }
        }
    }
}

3.和上面2的场景一样,通过依赖注入来创建对象。将上面2的代码进行再升级。

工厂模式 =>升级=> IOC容器的基础
IOC容器,一个自动化的工厂,还带配送,要什么给什么。彻底的解耦,高层不依赖于低层,依赖抽象。

namespace FatherStoryDIP
{
    /// <summary>
    /// 场景:父亲给孩子讲故事,只要给父亲一本书,他就可以照着书给孩子将故事。
    /// 有一天需求变了,不给书了,给报纸,读报纸上的新闻。
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            // 通过容器创建对象
            var sc = new ServiceCollection();
            // 接口对应实例进行注册
            //sc.AddScoped(typeof(IReader), typeof(Book));
            //var sp = sc.BuildServiceProvider();
            //IReader reader = sp.GetService<IReader>();
            //Father father = new Father(reader);
            //father.Read();

            // Unity创建容器 全程没有new对象
            var container = new UnityContainer();
            container.RegisterType<IReader, Book>();
            container.RegisterType<Father>();
            // 解析容器中的对象,用什么泛型中填什么
            var father = container.Resolve<Father>();
            father.Read();
            Console.ReadKey();
        }
    }

    /// <summary>
    /// 读物的接口
    /// </summary>
    public interface IReader
    {
        string GetContent();
    }

    public class Paper : IReader
    {
        public string GetContent()
        {
            return "王思聪被限制消费..";
        }
    }

    public class Book : IReader
    {
        public string GetContent()
        {
            return "从前有座山,山上有座庙...";
        }
    }

    public class Father
    {
        private IReader _reader { get; set; }

        public Father(IReader reader)
        {
            _reader = reader;
        }

        public void Read()
        {
            Console.WriteLine("爸爸给孩子开始讲故事了..");
            Console.WriteLine(_reader.GetContent());
        }
    }
}

 容器类似于一个登记本,生产的东西登记到容器中,用的时候直接从容器中取。
            当前代码用硬编码的方式注册,注册类型的方式有很多种
                1.配置文件,动态加载
               2.批量注册,将特殊标识的实体类(例:后缀为Service或者有某个特性)的全部注册到容器中
               3.通过反射,扫描程序集,找到你想要找到的类注册进来。例如后缀名为Service

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值