译C#使用设计模式和软件设计原则构建应用程序 PartIII
依赖注入
这个原则的要点是什么。为什么你不能对类的实例进行再次硬编码?当我们编码,测试的时候,让我们关注一件很重要的事情。希望你知道单元测试并知道它的重要性。也许在你做任何编码之前你都应该首先设计你的测试,因此你应该很熟悉测试驱动开发。为了定义新功能你应该去写测试,你应该尝试去实现并开始编码直到测试通过。让我们先看看之前的文章的代码。
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相关推荐
- java 设计模式:软件设计原则、面向对象理论、23 种设计模式
文章目录 软件设计原则 1.单一职责原则(Single Responsibility Principle) 2.开闭原则(Open Closed Principle) 3.里氏代换原则(Liskov ...
- 设计模式之软件设计原则篇
3.软件设计原则 本文的内容绝大部分借鉴了https://www.jianshu.com/u/cc272db15285的内容,感兴趣的小伙伴可以进入其简书浏览更细的内容,讲的非常好. 在软件开发中,为 ...
- 《设计模式详解》软件设计原则
<设计模式详解> 3.软件设计原则 3.1 开闭原则 示例 3.2 里式代换原则 反例 改进反例 3.3 依赖倒转原则 反例 改进反例 3.4 接口隔离原则 反例 改进反例 3.5 迪米特 ...
- 设计模式01 UML图,软件设计原则,创建型模式
概述 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1995年,由 Erich Gamma.Richard Helm.Ralph Johnson 和 Joh ...
- 从零开始学习Java设计模式 | 软件设计原则篇:开闭原则
从本讲开始,咱们就要开始学习第一章中的第三部分内容,即软件设计原则了. 在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据6条原则来开发程序,从而提高软件 ...
- 设计模式学习笔记1——概述 UML图 软件设计原则
目录 1.设计模式概述 1.1.软件设计模式产生背景 1.2.软件设计模式概念 1.3.学习设计模式的必要性 1.4.设计模式分类 1.4.1.创建型模式 1.4.2.结构型模式 1.4.3.行为型模 ...
- 【设计模式学习01】设计模式概述,UML图,软件设计原则
文章目录 1. 设计模式概述 1.1 软件设计模式的产生背景 1.2 软件设计模式的概念 1.3 学习设计模式的必要性 1.4 设计模式分类 2. UML图 2.1 类图概述 2.2 类图的作用 2. ...
- 软件设计模式——软件设计原则
摘要 设计模式(Design Pattern)是一套被反复使用.多数人知晓的.无数工程师实践的代码设计经验的总结,它是面向对象思想的高度提炼和模板化,使用设计模式是为了让代码具有更高的可重用性,更好的 ...
- 从零开始学习Java设计模式 | 软件设计原则篇:依赖倒转原则
在本讲,我将为大家介绍软件设计原则里面的第三个原则,即依赖倒转原则. 概述 什么是依赖倒转原则呢?我们来看一下下面这段描述: 高层模块不应该依赖低层模块,两者都应该依赖其抽象:抽象不应该依赖细节,细节 ...
最新文章
- u-boot2011.09 u-boot.img 的流程跟踪
- Python函数参数的五种类型
- 三手火箭载二手飞船送四名平民上太空,马斯克负责创造历史,另一位富豪出钱买单...
- excel 下拉框选择月份显示不同的日历_秒杀Excel的数据分析工具,几分钟教你完成数据填报...
- WebSocket数据加密——AES与RSA混合加密
- 四川对口高职本科学校计算机,2018四川对口高职本科学校有哪些
- matconvnet在ubuntu15.10下配置和使用方法
- 越是爱折腾的人就越容易成功
- 正确使用计算机键盘的方法是,电脑键盘指法练习及图示
- 小米CC9BL解锁、root方法测试
- Xcode6与Xcode5之间的细节差别(Precompile Prefix Header)
- python文件查重_海量文件查重SimHash和Minhash
- win7sp1怎么共享计算机,win7怎么升级到sp1?win7可以直接升级win7 sp1版本吗
- linux audit 源码分析,audit初探
- php 识别二维码内容
- docker安装linux-ubuntu桌面环境
- Android修行手册 - TextureView和SurfaceView的属性方法以及示例
- 基于Mathcad的LLC公式推导与化简(一)
- 【删库跑路】使用Binlog日志恢复误删的MySQL数据
- c#直接横向打印LocalReport
热门文章
- 参数调用不会改变参数值
- Java1.5语言新特性简单总结
- 北海市卫生学校计算机教室,北海卫校2021年招生简章_北海市卫生学校
- hdu 4309 最大流 + DFS
- C语言经典例84-一个偶数总能表示为两个素数之和
- 【计算机网络】应用层 : 万维网 和 HTTP 协议 ( 万维网概述 | HTTP 协议特点 | HTTP 协议连接方式 | HTTP 协议报文结构 | HTTP 请求报文 | HTTP 响应报文 )
- SQL SERVER深入学习学习资料参考
- sqoop导入数据到hive中元数据问题
- ArcGIS Engine开发前基础知识(4)
- java网络编程之TCP通讯