依赖注入

这个原则的要点是什么。为什么你不能对类的实例进行再次硬编码?当我们编码,测试的时候,让我们关注一件很重要的事情。希望你知道单元测试并知道它的重要性。也许在你做任何编码之前你都应该首先设计你的测试,因此你应该很熟悉测试驱动开发。为了定义新功能你应该去写测试,你应该尝试去实现并开始编码直到测试通过。让我们先看看之前的文章的代码。

public class DateBasedTaxFactory:ITaxFactory{Customer _customer;ITaxFactory _taxFactory;public DateBasedTaxFactory(Customer c, ITaxFactory cb){_customer = c;_taxFactory = cb;}public ITax GetTaxObject(){if (_customer.StateCode == "TX"&& DateTime.Now.Month == 4&& DateTime.Now.Day == 4)return new NoTax();elsereturn _taxFactory.GetTaxObject();}}

我们有DateBasedTaxFactory,当我们应该测试一下这个工厂是否能够正常的工作。 是否每年的4月4日这个Tax类型的返回值都应该是0.我们也许会创建一个如下的测试。

Customer cust = new Customer(){StateCode = "TX", County = "Travis", ZipCode = "78745"};DateBasedTaxFactory db = new DateBasedTaxFactory(cust, new CustomerBasedTaxFactory(cust));ITax tax = db.GetTaxObject();//test for no tax for a certain dateif(tax.CalculateTax(3m) != 0){throw new Exception("the value is supposed to be zero");}

这里有什么问题么?我们不能真正的测试这个!正如你可以在DateBasedTaxFactory中看到的,为了测试当前的日期,它直接使用DateTime对象的Now属性。除非你改变你系统的时间不然我们不能使得NoTax的条件满足。更改系统时间是不理想的。我们还能做其他的事情么?有时这个工厂类有个引用一个隐藏的属性,它是硬编码实现的,它依赖一些需要变化的东西。工厂类需要一个DateTime对象。它不需要DateTime是当前的日期。它不关注给它的日期是什么。为了告诉外面的世界这个类需要什么来工作我们需要使用依赖注入。这将允许我们的测试给他任何需要测试的日期。就如下面所示:

public class DateBasedTaxFactory : ITaxFactory
{Customer _customer;ITaxFactory _taxFactory;DateTime _dt;public DateBasedTaxFactory(Customer c, ITaxFactory cb,DateTime dt){_customer = c;_taxFactory = cb;_dt = dt;}public ITax GetTaxObject(){if (_customer.StateCode == "TX" && _dt.Month == 4 && _dt.Day == 4){return new NoTax();}elsereturn _taxFactory.GetTaxObject();}
} 

现在我们可以调整我们的测试来发送任何我们想要测试的日期。

Customer cust = new Customer(){StateCode = "TX",County ="Travis",ZipCode = "78745"};
DateBasedTaxFactory db = new DateBasedTaxFactory(cust, new CustomerBasedTaxFactory(cust),new DateTime(2001,4,4));
ITax tax = GetTaxObject();
//test for no tax for a certain date
if (tax.CalculateTax(3m) != 0)
{throw new Exception("the value is supposed to be zero");
}

单一原则/开闭原则

为什么你的对象应该只做一件事情?为什么你应该从不改变他们?显示生活变化了那么为什么代表生活变化的代码不能变化?让我们看看之前的稳重中的第一个版本的Order类。好的,假如说你的公司有一个坚定的政策,在您的系统中的主要程序集BusinessLogic.dll每两个月只有一个发布版本。假如有个bug或者在这之前需要做些变更,这将是一项繁琐艰巨的任务。但是我们可以用较少的麻烦来定义一个可补充的发布程序集。如果我们使用如下源代码:

public class Order
{List<OrderItem> _orderItems = new List<OrderItem>();public decimal CalculateTotal(Customer customer){decimal total = _orderItems.Sum((item)=>{return item.Cost * item.Quantity;});decimal tax;if (customer.StateCode == "TX")tax = total * .08m;else if (customer.StateCode == "FL")tax = total * .09m;elsetax = .03m;total = total + tax;return total;}
}

如果在TX的税费逻辑发生了变化或者需要一个新的State的税费,我们将必须要去修改Order对象。这将会造成 很大的臭味,因为我们需要去测试并发布BusinessLogic.dll.由于它有税费有关,如果事情发生了很大的变化并且他将要投入生产ASAP中是,法律和金钱是一个不错的选择。

从其他的文章中我们已经做了我们需要做的事情,例如:

 public interface ITax{decimal CalculateTax(decimal total);}public class TXTax:ITax{public decimal CalculateTax(decimal total){return total * 0.08m;}}public class CustomerBasedTaxFactory:ITaxFactory{Customer _customer;static Dictionary<string, ITax> stateTaxObjects = new Dictionary<string, ITax>();static Dictionary<string, ITax> countyTaxObjects = new Dictionary<string, ITax>();public CustomerBasedTaxFactory(Customer customer){_customer = customer;}public ITax GetTaxObject(){ITax tax;if(!string.IsNullOrEmpty(_customer.County)){if (!countyTaxObjects.Keys.Contains(_customer.StateCode)){tax = (ITax)Activator.CreateInstance("Tax", "Solid.taxes." + _customer.County + "CountyTax");countyTaxObjects.Add(_customer.StateCode, tax);}elsetax = countyTaxObjects[_customer.StateCode];}else{if (!stateTaxObjects.Keys.Contains(_customer.StateCode)){tax = (ITax)Activator.CreateInstance("Tax", "Solid.taxes." + _customer.StateCode + "Tax");stateTaxObjects.Add(_customer.StateCode, tax);}elsetax = stateTaxObjects[_customer.StateCode];}return tax;}}

我们有我们的TaxFactory来创建Tax对象并且所有的Tax逻辑都是在它的单独类中来完成的。因此到现在为止ITax类可以被引入到其他的程序集当中来做一些Tax相关的任务。Tax.dll。如果发生了变化,那么只需要在当前的程序集当中测试,并且它的附加程序集也不会有太多繁文缛节的事情。

好了,就这样吧,下次再见。

转载于:https://www.cnblogs.com/szkk/p/3917003.html

译C#使用设计模式和软件设计原则构建应用程序 PartIII相关推荐

  1. java 设计模式:软件设计原则、面向对象理论、23 种设计模式

    文章目录 软件设计原则 1.单一职责原则(Single Responsibility Principle) 2.开闭原则(Open Closed Principle) 3.里氏代换原则(Liskov ...

  2. 设计模式之软件设计原则篇

    3.软件设计原则 本文的内容绝大部分借鉴了https://www.jianshu.com/u/cc272db15285的内容,感兴趣的小伙伴可以进入其简书浏览更细的内容,讲的非常好. 在软件开发中,为 ...

  3. 《设计模式详解》软件设计原则

    <设计模式详解> 3.软件设计原则 3.1 开闭原则 示例 3.2 里式代换原则 反例 改进反例 3.3 依赖倒转原则 反例 改进反例 3.4 接口隔离原则 反例 改进反例 3.5 迪米特 ...

  4. 设计模式01 UML图,软件设计原则,创建型模式

    概述 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1995年,由 Erich Gamma.Richard Helm.Ralph Johnson 和 Joh ...

  5. 从零开始学习Java设计模式 | 软件设计原则篇:开闭原则

    从本讲开始,咱们就要开始学习第一章中的第三部分内容,即软件设计原则了. 在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据6条原则来开发程序,从而提高软件 ...

  6. 设计模式学习笔记1——概述 UML图 软件设计原则

    目录 1.设计模式概述 1.1.软件设计模式产生背景 1.2.软件设计模式概念 1.3.学习设计模式的必要性 1.4.设计模式分类 1.4.1.创建型模式 1.4.2.结构型模式 1.4.3.行为型模 ...

  7. 【设计模式学习01】设计模式概述,UML图,软件设计原则

    文章目录 1. 设计模式概述 1.1 软件设计模式的产生背景 1.2 软件设计模式的概念 1.3 学习设计模式的必要性 1.4 设计模式分类 2. UML图 2.1 类图概述 2.2 类图的作用 2. ...

  8. 软件设计模式——软件设计原则

    摘要 设计模式(Design Pattern)是一套被反复使用.多数人知晓的.无数工程师实践的代码设计经验的总结,它是面向对象思想的高度提炼和模板化,使用设计模式是为了让代码具有更高的可重用性,更好的 ...

  9. 从零开始学习Java设计模式 | 软件设计原则篇:依赖倒转原则

    在本讲,我将为大家介绍软件设计原则里面的第三个原则,即依赖倒转原则. 概述 什么是依赖倒转原则呢?我们来看一下下面这段描述: 高层模块不应该依赖低层模块,两者都应该依赖其抽象:抽象不应该依赖细节,细节 ...

最新文章

  1. u-boot2011.09 u-boot.img 的流程跟踪
  2. Python函数参数的五种类型
  3. 三手火箭载二手飞船送四名平民上太空,马斯克负责创造历史,另一位富豪出钱买单...
  4. excel 下拉框选择月份显示不同的日历_秒杀Excel的数据分析工具,几分钟教你完成数据填报...
  5. WebSocket数据加密——AES与RSA混合加密
  6. 四川对口高职本科学校计算机,2018四川对口高职本科学校有哪些
  7. matconvnet在ubuntu15.10下配置和使用方法
  8. 越是爱折腾的人就越容易成功
  9. 正确使用计算机键盘的方法是,电脑键盘指法练习及图示
  10. 小米CC9BL解锁、root方法测试
  11. Xcode6与Xcode5之间的细节差别(Precompile Prefix Header)
  12. python文件查重_海量文件查重SimHash和Minhash
  13. win7sp1怎么共享计算机,win7怎么升级到sp1?win7可以直接升级win7 sp1版本吗
  14. linux audit 源码分析,audit初探
  15. php 识别二维码内容
  16. docker安装linux-ubuntu桌面环境
  17. Android修行手册 - TextureView和SurfaceView的属性方法以及示例
  18. 基于Mathcad的LLC公式推导与化简(一)
  19. 【删库跑路】使用Binlog日志恢复误删的MySQL数据
  20. c#直接横向打印LocalReport

热门文章

  1. 参数调用不会改变参数值
  2. Java1.5语言新特性简单总结
  3. 北海市卫生学校计算机教室,北海卫校2021年招生简章_北海市卫生学校
  4. hdu 4309 最大流 + DFS
  5. C语言经典例84-一个偶数总能表示为两个素数之和
  6. 【计算机网络】应用层 : 万维网 和 HTTP 协议 ( 万维网概述 | HTTP 协议特点 | HTTP 协议连接方式 | HTTP 协议报文结构 | HTTP 请求报文 | HTTP 响应报文 )
  7. SQL SERVER深入学习学习资料参考
  8. sqoop导入数据到hive中元数据问题
  9. ArcGIS Engine开发前基础知识(4)
  10. java网络编程之TCP通讯