Design Patterns ----- Принцип инверсии зависимостей

Во-первых, принцип введения

1, официальное определение

Принцип инверсии зависимостей, аббревиатура DIP , полное название ЗАВИСИМОСТИ Принцип инверсии.

原始 定义: Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Официальный перевод: модули высокого уровня не должны зависеть от модулей низкого уровня, оба из которых должны полагаться на его абстрактно, абстрактное не должны полагаться на детали, детали должны зависеть от абстрактного.

2, его собственное понимание

2,1, объяснить принципы

Приведенное выше определение не трудно понять, в основном, содержит два значения:

1) модуль слой не должен быть напрямую зависят от конкретной реализации базовых модулей, но должен зависеть от базовой абстракции. Другими слова, зависимости между модулями не происходит через абстракцию, никаких прямых зависимостей между классами, которые зависимость генерируемых с помощью интерфейса или абстрактного класса.

2) абстрактный интерфейс класса, и не должно зависеть от класса реализации, в то время как интерфейс зависимого класса реализации или абстрактного класса. Это на самом деле Излишне говорить, что хорошо понимают, «Oriented Programming Interface» подумал, что это лучший вариант.

2,2, был «вверх ногами» зависимость

По сравнению с традиционным дизайном архитектуры программного обеспечения, такими , как мы часто говорим , что классическая трехуровневая архитектура, слой UI зависит от BLL, BLL слой зависит от DAL. Поскольку каждый слой зависит от базовой реализации, так что , когда слой структуры изменяется, она должна была бы иметь верхний изменения, такие , как мы DAL логики , которые могут вызвать изменения BLL и UI слой все будет изменен, эта архитектура смешно! Ну, на этот раз , если мы изменим концепцию дизайна, модуль высокого уровня не зависят от низкого уровня прямого, а полагаться на абстрактных блоках низкого уровня , проявляющиеся мы добавят слой IBLL, которые определяют бизнес - логику интерфейс, уровень UI зависит от IBLL слой, слой реализует BLL IBLL внутри интерфейса, поэтому конкретная бизнес - логика определяется в BLL внутри, на этот раз , если мы BLL внутри логических изменений, пока поведение не меняется интерфейс, верхний интерфейс , который не имеет каких - либо изменений.

В классической трехуровневой внутри, чтобы достигнуть модулей высокого уровня, непосредственно зависящих от модулей низкого уровня, когда мы будем опираться на абстракции базового модуля модуля высокого уровня, так же, как зависимость «инверсии» из. Это Dependency Inversion происхождения. Опираясь на перевернутом вниз, он может сделать архитектуру более устойчивой, более гибкой и лучше реагировать на изменения спроса.

2.3, в зависимости от цели инвертированного

Выше этого, интерфейс слой увеличивается до достижения трехуровневой инверсии архитектуры зависимостей внутри, его цель состоит в том, чтобы уменьшить сцепление между слоями, что делает конструкцию более гибкой. С этого момента, Принцип инверсии зависимостей является «слабосвязанная» хорошо отражает дизайн.

Во-вторых, пример сценария

Когда в начале статьи сказало, инверсия зависимости является одним из принципов дизайна шаблонов проектирования, то мы имеем так много шаблонов проектирования, шаблоны проектирования, которые следуют принципу Dependency Inversion его? Это больше, например, как наш общий фабричный метод. Следующие блоггеры говорят, что это сочетание как принцип инверсии зависимостей способен сделать конструкцию более гибкие сценарии использования для.

Сцена Описание: Помните ли вы в романтической встрече: интерфейсы и абстрактные классы в этой коллекции , которая представила пример устройства, это продолжают использовать этот сценарий , чтобы показать. Есть много типов устройств, каждое устройство имеет два пути для входа и захвата, чтобы начать собирать устройство, DeviceService эту услугу, мы имеем только начало MML и TL2 оба типа устройств, проверить наш дизайн - код.

Пример кода:

  //MML类型的设备
    public class DeviceMML
    {
        public void Login()
        {
            Console.WriteLine("MML设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("MML设备采集");
            return true;
        }
    }

    //TL2类型设备
    public class DeviceTL2
    {
        public void Login()
        {
            Console.WriteLine("TL2设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("TL2设备采集");
            return true;
        }
    }

    //设备采集的服务
    public class DeviceService
    {
        private DeviceMML MML = null;
        private DeviceTL2 TL2 = null;
        private string m_type = null;
        //构造函数里面通过类型来判断是哪种类型的设备
        public DeviceService(string type)
        {
            m_type = type;
            if (type == "0")
            {
                MML = new DeviceMML();
            }
            else if (type == "1")
            {
                TL2 = new DeviceTL2();
            }
        }

        public void LoginDevice()
        {
            if (m_type == "0")
            {
                MML.Login();
            }
            else if (m_type == "1")
            {
                TL2.Login();
            }
        }

        public bool DeviceSpider()
        {
            if (m_type == "0")
            {
                return MML.Spider();
            }
            else if (m_type == "1")
            {
                return TL2.Spider();
            }
            else
            {
                return true;
            }
        }
    }

Главное внутри вызова функции

   class Program
    {

        static void Main(string[] args)
        {
            var oSpider = new DeviceService("1");
            oSpider.LoginDevice();
            var bRes = oSpider.DeviceSpider();
            
            Console.ReadKey();
        }

После выше разработки кода, тестирование, развертывание, он-лайн. Может функционировать должным образом, выглядит как и все в порядке.

День за днем, год за годом. Тогда компания пришла два новых устройства TELNET и оборудования типа TL5. Таким образом, есть процедуры APE слишком заняты, сверхурочные, закончить работу! Таким образом, это становится код:

   //MML类型的设备
    public class DeviceMML
    {
        public void Login()
        {
            Console.WriteLine("MML设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("MML设备采集");
            return true;
        }
    }

    //TL2类型设备
    public class DeviceTL2
    {
        public void Login()
        {
            Console.WriteLine("TL2设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("TL2设备采集");
            return true;
        }
    }

    //TELNET类型设备
    public class DeviceTELNET
    {
        public void Login()
        {
            Console.WriteLine("TELNET设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("TELNET设备采集");
            return true;
        }
    }

    //TL5类型设备
    public class DeviceTL5
    {
        public void Login()
        {
            Console.WriteLine("TL5设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("TL5设备采集");
            return true;
        }
    }


    //设备采集的服务
    public class DeviceService
    {
        private DeviceMML MML = null;
        private DeviceTL2 TL2 = null;
        private DeviceTELNET TELNET = null;
        private DeviceTL5 TL5 = null;
        private string m_type = null;
        //构造函数里面通过类型来判断是哪种类型的设备
        public DeviceService(string type)
        {
            m_type = type;
            if (type == "0")
            {
                MML = new DeviceMML();
            }
            else if (type == "1")
            {
                TL2 = new DeviceTL2();
            }
            else if (type == "2")
            {
                TELNET = new DeviceTELNET();
            }
            else if (type == "3")
            {
                TL5 = new DeviceTL5();
            }
        }

        public void LoginDevice()
        {
            if (m_type == "0")
            {
                MML.Login();
            }
            else if (m_type == "1")
            {
                TL2.Login();
            }
            else if (m_type == "2")
            {
                TELNET.Login();
            }
            else if (m_type == "3")
            {
                TL5.Login();
            }
        }

        public bool DeviceSpider()
        {
            if (m_type == "0")
            {
                return MML.Spider();
            }
            else if (m_type == "1")
            {
                return TL2.Spider();
            }
            else if (m_type == "2")
            {
                return TELNET.Spider();
            }
            else if (m_type == "3")
            {
                return TL5.Spider();
            }
            else
            {
                return true;
            }
        }
    }

Например, мы хотим, чтобы начать сбор типа TL5 устройства, так что вызовы могут быть достигнуты:

        static void Main(string[] args)
        {
            var oSpider = new DeviceService("3");
            oSpider.LoginDevice();
            var bRes = oSpider.DeviceSpider();
         
            Console.ReadKey();
        }

Потребовалось девять тигров силы, он, наконец, может быть достигнут. Но это был период времени, появляются новые типы оборудования это? Он не собирается работать сверхурочно, но и изменить. Это продолжается, я считаю, что это бездонная яма, плюс более длительное время, проект опытных разработчиков более легко изменений, на этот раз для изменения, это сопоставимо с затратами на поддержании разработки нового проекта. И, с увеличением типа устройства, код внутри заполнен много, если ... иначе, этот код просто плохие люди не могут смотреть.

Исходя из этой ситуации, если у нас было время, чтобы рассмотреть дизайном этой системы является инверсией зависимости, то эффект может быть разным. Давайте посмотрим на то, как решить вышеуказанные проблемы Dependency Inversion это?

    //定义一个统一接口用于依赖
    public interface IDevice
    {
        void Login();
        bool Spider();
    }

    //MML类型的设备
    public class DeviceMML : IDevice
    {
        public void Login()
        {
            Console.WriteLine("MML设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("MML设备采集");
            return true;
        }
    }

    //TL2类型设备
    public class DeviceTL2 : IDevice
    {
        public void Login()
        {
            Console.WriteLine("TL2设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("TL2设备采集");
            return true;
        }
    }

    //TELNET类型设备
    public class DeviceTELNET : IDevice
    {
        public void Login()
        {
            Console.WriteLine("TELNET设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("TELNET设备采集");
            return true;
        }
    }

    //TL5类型设备
    public class DeviceTL5 : IDevice
    {
        public void Login()
        {
            Console.WriteLine("TL5设备登录");
        }

        public bool Spider()
        {
            Console.WriteLine("TL5设备采集");
            return true;
        }
    }


    //设备采集的服务
    public class DeviceService
    {
        private IDevice m_device;
        public DeviceService(IDevice oDevice)
        {
            m_device = oDevice;
        }

        public void LoginDevice()
        {
            m_device.Login();
        }

        public bool DeviceSpider()
        {
            return m_device.Spider();
        }
    }

вызов

     static void Main(string[] args)
        {
            var oSpider = new DeviceService(new DeviceTL5());
            oSpider.Login();
            var bRes = oSpider.Spider();

            Console.ReadKey();
        }

Код Описание: выше решение, мы определяем интерфейс чтения компакт - дисков для верхних зависящих от услуг, то есть, служба верхний слой (называемый здесь DeviceService) зависит только от интерфейса чтения компакт - дисков для конкретной категории мы независимо от того, до тех пор , как интерфейс поведение не меняется, добавлять новые типы устройств, высокий уровень обслуживания без внесения каких - либо изменений. Такая конструкция уменьшает связь между слоями может быть хорошо адаптирована к изменениям спроса, значительно повышает эксплуатационную надежность кода. О, не это выглядело немного знакомым? Это немного не похож на шаблон проектирования? На самом деле, принципы разработки шаблонов проектирования основаны на этом.

В-третьих, использование Unity для достижения Dependency Inversion

Он говорит, что так много, мы говорим о преимуществах инверсии зависимостей, то, как именно достичь конкретных и использовать его в нашем проекте?

Перед введением Dependency Inversion, как использовать конкретные, мы должны ввести понятия, связанные с контейнером МОК, мы посмотрим на отношения между ними.

Принцип инверсии зависимостей (DIP): принцип проектирования архитектуры программного обеспечения (абстрактное понятие).

Инверсия управления (IoC): один вид обратного потока, а также зависимый образ интерфейса (конкретная реализация DIP). Эта концепция немного меньше хорошо изучены и объяснены, в буквальном смысле, зависит от самого приложения не несет ответственности за создание и поддержание объекта, а дать его внешний контейнер (такой как единства) быть ответственным, поэтому его контролировать переносится из приложения на внешний контейнер IoC, то есть для достижения контроля под названием инверсия. Тип А, например, требует использования экземпляра типа В, созданный В. Пример А не быть ответственным, но создатель внешнего контейнера.

Внедрение зависимостей (Д. И.): реализация IoC один для обратной зависимости от конкретной реализации (IoC). Боуэн также есть много , чтобы сказать , который МОК также известный как DI, на самом деле, по мнению блоггеров понять, DI МОК должна быть конкретной реализации, например, как мы реализуем Инверсия управления, ответ должен быть достигнут путем инъекции зависимостей.

IoC контейнер: зависимость инъекции рамки для отображения зависит, создание объектов и управление жизненным циклом (DI рамки), автоматически создавать, поддерживать зависимые объекты.

О IoC контейнера, каждый язык имеет свои собственные сложные решения, такие как Java, внутри одной из величайших рамочным Spring, .net внутри легкого Autofac и так далее. Потому что блоггеры на языке С # относительно знакомы, здесь сочетание C # контейнера внутри МОК для иллюстрации. .net внутри контейнеров обычно IOC:

Конечно, есть другой контейнер МОК не будет перечислять их здесь. Блоггеры или чуть ниже этого контейнер взгляда Единства МОК в реализации конкретной зависят перевернутые.

1, Единство введены

Единство, как вводить? Наш волшебный NuGet послал пригодится. Последняя версия Unity пришел к 4.0.1.

После успешной установки в основном представляет три библиотеки DLL.

2, единство общих API,

UnityContainer.RegisterType<ITFrom,TTO>();

UnityContainer.RegisterType< ITFrom, TTO >();

UnityContainer.RegisterType< ITFrom, TTO >("keyName");

IEnumerable<T> databases = UnityContainer.ResolveAll<T>();

IT instance = UnityContainer.Resolve<IT>();

T instance = UnityContainer.Resolve<T>("keyName");

UnitContainer.RegisterInstance<T>("keyName",new T());

UnityContainer.BuildUp(existingInstance);

IUnityContainer childContainer1 = parentContainer.CreateChildContainer();

3, путем инъекции пример кода

3.1, регистр режима по умолчанию

Еще выше сценарий в качестве примера, мы вводили DeviceMML класса реализации.

    class Program
    {
        private static IUnityContainer container = null;
        static void Main(string[] args)
        {
            RegisterContainer();
            var oSpider = container.Resolve<IDevice>();
            oSpider.Login();
            var bRes = oSpider.Spider();

            Console.ReadKey();
        }

        /// <summary>
        /// 代码注入
        /// </summary>
        public static void RegisterContainer()
        {
            container = new UnityContainer();
            container.RegisterType<IDevice, DeviceMML>();  //默认注册方式,如果后面再次默认注册会覆盖前面的
        }
    }

Операционные результаты

3,2, зарегистрированных в наименовании

Введенный выше режим по умолчанию, можно вводить только пример конкретный, если нам нужно вводить несколько экземпляров типа это? Проверьте наш метод RegisterType () имеет несколько перегружен.

   class Program
    {
        private static IUnityContainer container = null;
        static void Main(string[] args)
        {
            RegisterContainer();
            var oSpider = container.Resolve<IDevice>("TL5");
            oSpider.Login();
            var bRes = oSpider.Spider();

            Console.ReadKey();
        }

        /// <summary>
        /// 代码注入
        /// </summary>
        public static void RegisterContainer()
        {
            container = new UnityContainer();
           container.RegisterType<IDevice, DeviceMML>("MML");  //默认注册(无命名),如果后面还有默认注册会覆盖前面的
            container.RegisterType<IDevice, DeviceTELNET>("Telnet");  //命名注册
            container.RegisterType<IDevice, DeviceTL2>("TL2");  //命名注册
            container.RegisterType<IDevice, DeviceTL5>("TL5");  //命名注册
        }
    }

Операционные результаты

4, в качестве примера профиля впрыска

Добавлено следующим App.config или Web.config внутри:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity>
    <!--容器-->
    <containers>
      <container name="Spider">
        <!--映射关系-->
        <register type="ESTM.Spider.IDevice,ESTM.Spider"  mapTo="ESTM.Spider.DeviceMML,ESTM.Spider" name="MML"></register>
        <register type="ESTM.Spider.IDevice,ESTM.Spider"  mapTo="ESTM.Spider.DeviceTELNET,ESTM.Spider" name="TELNET"></register>
        <register type="ESTM.Spider.IDevice,ESTM.Spider"  mapTo="ESTM.Spider.DeviceTL2,ESTM.Spider" name="TL2"></register>
        <register type="ESTM.Spider.IDevice,ESTM.Spider"  mapTo="ESTM.Spider.DeviceTL5,ESTM.Spider" name="TL5"></register>
      </container>
    </containers>
  </unity>
</configuration>

Профили регистрируются в коде внутри:

namespace ESTM.Spider
{
    class Program
    {
        private static IUnityContainer container = null;
        static void Main(string[] args)
        {
            ContainerConfiguration();
            var oSpider = container.Resolve<IDevice>("TL5");
            oSpider.Login();
            var bRes = oSpider.Spider();

            Console.ReadKey();
        }

        /// <summary>
        /// 配置文件注入
        /// </summary>
        public static void ContainerConfiguration()
        {
            container = new UnityContainer();
            UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
            configuration.Configure(container, "Spider");
        }

    }
}

Результат:

Код Описание

(1)

<register type="ESTM.Spider.IDevice,ESTM.Spider"  mapTo="ESTM.Spider.DeviceMML,ESTM.Spider" name="MML"></register>

Внутри узла, тип абстрактного объекта, МАПТО целевой конкретный экземпляр объекта, имя псевдоним экземпляра объекта.

(2) множество узлов может быть расположено внутри App.config другого названия отличается в зависимости от конфигурации объектов.

(3) введение гибкого профиля является то, что разъединение. Почему вы говорите? Представьте себе, если мы чтения компакт-дисков в соответствует на интерфейс слоя и DeviceMML, DeviceTELNET, DeviceTL2, DeviceTL5 класс реализации и т.д. В другом слое внутренней реализации, наш UI слой (здесь, этот слой, соответствующий консольной программы) нужно только добавить интерфейс чтения компакт-дисков опорный слой, опорный слой достигается без добавления, по профилю впрыска, во время выполнения для достижения динамического класса вводится внутрь к слою UI. Таким образом, слой пользовательского интерфейса на слое, чтобы добиться реализации развязки, реализации конкретных изменений внутри логического уровня, слой пользовательского интерфейса, который не имеет вносить какие-либо изменения.

IV Резюме

Это принцип инверсии зависимостей объяснить в основном закончена. По словам блоггер , понимание этих принципов является теоретическим руководством шаблонов проектирования шаблонов дизайна и шаблон дизайна является применением бетона из этих теорий . Упомянутые 1000 10000, чтобы получить знать режим дизайна, мы должны сначала понять принципы шаблонов проектирования , чтобы следовать, независимо от того , каких шаблонов проектирования будет следовать один или более из этих принципов. Конечно, эта статья может быть понята неположенным место, приветствует Даниил указал.

рекомендация

отwww.cnblogs.com/MessiXiaoMo3334/p/11827951.html