依赖注入的那些事儿(下)[转载]
1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace SetterInjection 7: {
8: class Program 9: {
10: static void Main(string[] args) 11: {
12: IServiceClass serviceA = new ServiceClassA(); 13: IServiceClass serviceB = new ServiceClassB(); 14: ClientClass client = new ClientClass(); 15: 16: client.Set_ServiceImpl(serviceA); 17: client.ShowInfo(); 18: client.Set_ServiceImpl(serviceB); 19: client.ShowInfo(); 20: } 21: } 22: } 运行结果如下:
图3.2 Setter注入运行结果 3.1.2 构造注入 另外一种依赖注入方式,是通过客户类的构造函数,向客户类注入服务类实例。 构造注入(Constructor Injection)是指在客户类中,设置一个服务类接口类型的数据成员,并以构造函数为注入点,这个构造函数接受一个具体的服务类实例为参数,并将它赋给服务类接口类型的数据成员。
图3.3 构造注入示意 图3.3是构造注入的示意图,可以看出,与Setter注入很类似,只是注入点由Setter方法变成了构造方法。这里要注意,由于构造注入只能在实例化客户类时注入一次,所以一点注入,程序运行期间是没法改变一个客户类对象内的服务类实例的。 由于构造注入和Setter注入的IServiceClass,ServiceClassA和ServiceClassB是一样的,所以这里给出另外ClientClass类的示例代码。 Code:ClientClass1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace ConstructorInjection 7: {
8: internal class ClientClass 9: {
10: private IServiceClass _serviceImpl; 11: 12: public ClientClass(IServiceClass serviceImpl) 13: {
14: this._serviceImpl = serviceImpl; 15: } 16: 17: public void ShowInfo() 18: {
19: Console.WriteLine(_serviceImpl.ServiceInfo()); 20: } 21: } 22: } 可以看到,唯一的变化就是构造函数取代了Set_ServiceImpl方法,成为了注入点。 3.1.3 依赖获取 上面提到的注入方式,都是客户类被动接受所依赖的服务类,这也符合“注入”这个词。不过还有一种方法,可以和依赖注入达到相同的目的,就是依赖获取。 依赖获取(Dependency Locate)是指在系统中提供一个获取点,客户类仍然依赖服务类的接口。当客户类需要服务类时,从获取点主动取得指定的服务类,具体的服务类类型由获取点的配置决定。 可以看到,这种方法变被动为主动,使得客户类在需要时主动获取服务类,而将多态性的实现封装到获取点里面。获取点可以有很多种实现,也许最容易想到的就是建立一个Simple Factory作为获取点,客户类传入一个指定字符串,以获取相应服务类实例。如果所依赖的服务类是一系列类,那么依赖获取一般利用Abstract Factory模式构建获取点,然后,将服务类多态性转移到工厂的多态性上,而工厂的类型依赖一个外部配置,如XML文件。 不过,不论使用Simple Factory还是Abstract Factory,都避免不了判断服务类类型或工厂类型,这样系统中总要有一个地方存在不符合OCP的if…else或switch…case结构,这种缺陷是Simple Factory和Abstract Factory以及依赖获取本身无法消除的,而在某些支持反射的语言中(如C#),通过将反射机制的引入彻底解决了这个问题(后面讨论)。 下面给一个具体的例子,现在我们假设有个程序,既可以使用Windows风格外观,又可以使用Mac风格外观,而内部业务是一样的。
图3.4 依赖获取示意 上图乍看有点复杂,不过如果读者熟悉Abstract Factory模式,应该能很容易看懂,这就是Abstract Factory在实际中的一个应用。这里的Factory Container作为获取点,是一个静态类,它的“Type构造函数”依据外部的XML配置文件,决定实例化哪个工厂。下面还是来看示例代码。由于不同组件的代码是相似的,这里只给出Button组件的示例代码,完整代码请参考文末附上的完整源程序。 Code:按钮接口1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace DependencyLocate 7: {
8: internal interface IButton 9: {
10: String ShowInfo(); 11: } 12: }Code:Windows风格按钮 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace DependencyLocate 7: {
8: internal sealed class WindowsButton : IButton 9: {
10: public String Description { get; private set; }
11: 12: public WindowsButton() 13: {
14: this.Description = "Windows风格按钮"; 15: } 16: 17: public String ShowInfo() 18: {
19: return this.Description; 20: } 21: } 22: }Code:Mac风格按钮 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace DependencyLocate 7: {
8: internal sealed class MacButton : IButton 9: {
10: public String Description { get; private set; }
11: 12: public MacButton() 13: {
14: this.Description = " Mac风格按钮"; 15: } 16: 17: public String ShowInfo() 18: {
19: return this.Description; 20: } 21: } 22: }Code:工厂接口 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace DependencyLocate 7: {
8: internal interface IFactory 9: {
10: IWindow MakeWindow(); 11: 12: IButton MakeButton(); 13: 14: ITextBox MakeTextBox(); 15: } 16: }Code:Windows组件工厂 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace DependencyLocate 7: {
8: internal sealed class WindowsFactory : IFactory 9: {
10: public IWindow MakeWindow() 11: {
12: return new WindowsWindow(); 13: } 14: 15: public IButton MakeButton() 16: {
17: return new WindowsButton(); 18: } 19: 20: public ITextBox MakeTextBox() 21: {
22: return new WindowsTextBox(); 23: } 24: } 25: }Code:Mac组件工厂 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace DependencyLocate 7: {
8: internal sealed class MacFactory : IFactory 9: {
10: public IWindow MakeWindow() 11: {
12: return new MacWindow(); 13: } 14: 15: public IButton MakeButton() 16: {
17: return new MacButton(); 18: } 19: 20: public ITextBox MakeTextBox() 21: {
22: return new MacTextBox(); 23: } 24: } 25: }Code:获取点 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: using System.Xml; 6: 7: namespace DependencyLocate 8: {
9: internal static class FactoryContainer 10: {
11: public static IFactory factory { get; private set; }
12: 13: static FactoryContainer() 14: {
15: XmlDocument xmlDoc = new XmlDocument(); 16: xmlDoc.Load("http://www.cnblogs.com/Config.xml");
17: XmlNode xmlNode = xmlDoc.ChildNodes[1].ChildNodes[0].ChildNodes[0]; 18: 19: if ("Windows" == xmlNode.Value)
20: {
21: factory = new WindowsFactory(); 22: } 23: else if ("Mac" == xmlNode.Value)
24: {
25: factory = new MacFactory(); 26: } 27: else 28: {
29: throw new Exception("Factory Init Error");
30: } 31: } 32: } 33: }Code:测试代码 1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace DependencyLocate 7: {
8: class Program 9: {
10: static void Main(string[] args) 11: {
12: IFactory factory = FactoryContainer.factory; 13: IWindow window = factory.MakeWindow(); 14: Console.WriteLine("创建 " + window.ShowInfo());
15: IButton button = factory.MakeButton(); 16: Console.WriteLine("创建 " + button.ShowInfo());
17: ITextBox textBox = factory.MakeTextBox(); 18: Console.WriteLine("创建 " + textBox.ShowInfo());
19: 20: Console.ReadLine(); 21: } 22: } 23: } (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

![依赖注入的那些事儿(下)[转载]](http://images.cnblogs.com/cnblogs_com/leoo2sk/WindowsLiveWriter/a5703ca6e7d5_D180/05_3.jpg)
![依赖注入的那些事儿(下)[转载]](http://images.cnblogs.com/cnblogs_com/leoo2sk/WindowsLiveWriter/a5703ca6e7d5_D180/06_3.jpg)
![依赖注入的那些事儿(下)[转载]](http://images.cnblogs.com/cnblogs_com/leoo2sk/WindowsLiveWriter/a5703ca6e7d5_D180/07_3.jpg)