面向對象設計(OOD)有助於我們開發出高性能、易擴展以及易復用的程式。其中,OOD有一個重要的思想那就是依賴倒置原則(DIP)。 依賴倒置原則(DIP):一種軟體架構設計的原則(抽象概念) 控制反轉(IoC):一種反轉流、依賴和介面的方式(DIP的具體實現方式) 依賴註入(DI):IoC的一種實現方 ...
面向對象設計(OOD)有助於我們開發出高性能、易擴展以及易復用的程式。其中,OOD有一個重要的思想那就是依賴倒置原則(DIP)。
依賴倒置原則(DIP):一種軟體架構設計的原則(抽象概念)
控制反轉(IoC):一種反轉流、依賴和介面的方式(DIP的具體實現方式)
依賴註入(DI):IoC的一種實現方式,用來反轉依賴(IoC的具體實現方式)
IoC容器:依賴註入的框架,用來映射依賴,管理對象創建和生存周期(DI框架)、
Unity:是微軟推出的IOC框架
TDD:測試驅動開發,是敏捷開發中的一項核心實踐和技術,也是一種設計方法論
上面的內容都是抄的(英文不好,放在這裡備查),相關的內容看了一些,不明覺厲。
曾經寫了一個酒店讀寫房卡的程式,不同的酒店門鎖是不一樣的,同一個酒店也有可能更換門鎖,程式流程:
1.通過Api獲取當前酒店的門鎖類型
2.如果需要則下載對應門鎖的dll
3.實現讀寫功能
一、定義介面
新建一個類庫(Lock.Interface),代碼如下:
namespace Lock { public interface ILock { /// <summary> /// 門鎖初始化 /// </summary> /// <param name="password">初始化密碼</param> /// <returns></returns> bool Init(int password); } }
是不是算是IoC了?(我不確定)
二、單元測試
新建一個單元測試項目(Lock.Tests),代碼如下:
1.門鎖A單元測試
/// <summary> /// 門鎖A測試 /// </summary> [TestClass()] public class LockATests { /// <summary> /// 初始化,password為正奇數 /// </summary> [TestMethod()] public void InitTest() { ILock l = new LockA(); var ret = l.Init(1); Assert.AreEqual(ret, true); ret = l.Init(2); Assert.AreEqual(ret, false); ret = l.Init(-1); Assert.AreEqual(ret, false); } }
2.門鎖B單元測試
/// <summary> /// 門鎖B測試 /// </summary> [TestClass()] public class LockBTests { /// <summary> /// 初始化測試,password為正偶數 /// </summary> [TestMethod()] public void InitTest() { ILock l = new LockB(); var ret = l.Init(1); Assert.AreEqual(ret, false); ret = l.Init(2); Assert.AreEqual(ret, true); ret = l.Init(-1); Assert.AreEqual(ret, false); }
顯然編譯都不能通過(不能通過編譯也是一種測試)
三、定義類
1.創建門鎖A類庫(Lock.LockA),代碼如下:
/// <summary> /// 門鎖A /// </summary> public class LockA : ILock { /// <summary> /// 初始化 /// </summary> /// <param name="password">正確密碼是正奇數</param> /// <returns></returns> public bool Init(int password) { return password > 0 && (password % 2) == 1; } }
2.創建門鎖B類庫(Lock.LockB),代碼如下:
/// <summary> /// 門鎖B /// </summary> public class LockB : ILock { /// <summary> /// 初始化 /// </summary> /// <param name="password">正確密碼是正偶數</param> /// <returns></returns> public bool Init(int password) { return password > 0 && (password % 2) == 0; } }
分別編譯成功後,回到測試項目,添加引用,編譯通過,運行測試:
算不算TDD?
四、主程式
1.添加控制台項目
2.添加Unity(5.8.6)包
3.修改App.Config為:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Unity.Configuration, Version=5.2.1.0, Culture=neutral, PublicKeyToken=6d32ff45e0ccc69f" />
<!--上一些的內容網上複製過來有錯誤,後來查看UnityConfigurationSection的定義,複製了對應的程式集
type="命名空間.類名,程式集"
-->
</configSections>
<unity>
<containers>
<container name="LockA">
<register type="Lock.ILock,Lock.Interface" mapTo="Lock.LockA,Lock.LockA" ></register>
</container>
<container name="LockB">
<register type="Lock.ILock,Lock.Interface" mapTo="Lock.LockB,Lock.LockB"></register>
</container>
</containers>
</unity>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
4.引用介面
5.Main方法如下:
static void Main(string[] args) { var container = new UnityContainer(); UnityConfigurationSection config = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName); config.Configure(container, "LockA");
ILock l = container.Resolve<ILock>(); Console.WriteLine(l.Init(2)); Console.WriteLine(l.Init(1)); Console.WriteLine(l.Init(-1));
Console.ReadKey(); }
6.複製門鎖A的dll複製到運行目錄
7.運行結果如為:False、True、False,是門鎖A的結果
8.將“LockA”改成“LockB”,並將門鎖B的dll複製到運行目錄,運行結果為True、False、False是門鎖B的結果
算DI吧?咱都用了Unity了。
至此,基本實現了想要的功能,未來新酒店要增加門鎖C、門鎖D都沒問題,只有老酒店改成門鎖E的問題沒解決(估計可以通過動態修改config文件實現,也不知道有沒有更好地辦法)。