Professional Asp.Net Design Pattens 读书笔记(第1,2章)
一、介绍
这2章主要介绍了目前比较流行的一些面向对象的模式的概念, OOAD的一些原则,在书中其实只是提到了这些概念的冰山一角,要真正掌握这些概念和原理是一个非常漫长的过程,可能专心研究上1,2年都不一定能够很好的理解,所以这里就不做过多的解释了,需要自己去慢慢琢磨了。
这些概念主要包括:1:23种常用设计模式
推荐的学习材料:入门:《大话设计模式》;《Head First 设计模式》; DoFactory
提高:《C# 3.0设计模式》 博客园以及MSDN WebCast有一个系列视频教程2:OOAD的原则:KISS /SOLID
这些个原则理解起来不难,但真正掌握并实践还是需要很长的时间。可以看看CodeProject上的一篇《How I Explained OOD To My Wife》 博客园里有中文的翻译版本3:模式
Repository , Unit of Work, Data Mapper, Active Record, Transaction Script 等等必须是《企业应用架构模式》
4: TDD, DDD, BDD等
测试驱动开发(TDD) 基本没有关注过,最近实践了一下,说的简单一点就是先写单元测试,再写业务代码,最好还是自己google吧。领域驱动设计(DDD)目前市面上好的书有2本,《领域驱动设计:软件核心复杂性应对之道》 和《领域驱动设计与模式实战》 行为驱动设计BDD 没接触过;
二、如何选择和应用模式
1.不能在不了解这个模式的情况下就使用它(好像有点废话),最重要的就是尽可能多的从抽象和具体2个方面来学习和实践各种模式,你可以为一种模式创建多种实现,实践得越多,你对模式的意图就越了解。另外你也可以对一个问题使用不同的模式去解决。
2.是否需要引入复杂的设计模式?在开发人员学习模式的时候使用一种模式去解决所有问题是很常见的。你必须要衡量这种模式的收益是否值得。是否符合KISS原则
3.以更加抽象的眼光去看待问题,把每一个相关的模式的意图写下来,看看是否适合解决你的问题,请记住,设计模式是高层次的解决方案,尝试让问题更加抽象化,不要过于关注细节
4.当你使用一个模式解决了一个问题的时候,需要多考虑与这个模式类似的其他模式,也许你会发现跟适合的。
5.封装变化点。寻找应用程序中将会变化的地方,比如某个折扣方案会随着时间的推移而变化,那就寻找一个模式来解决这个变化,使得他的变化不会导致应用程序的其他部分改变。
6. 使用模式的时候可以在命名上标示出这个模式,比如使用了策略模式,与之相关的类就可以命名为XXXStrategy,这样可以让别人更好的理解。
三、一个简单的例子
1:反面教材
存在的问题:
(1) ProductService 以来 ProductRepository, Repository改了 Service也得改
(2) Service中的 GetAllProductsIn方法几乎不可测试 ,首先2个类是耦合的,其次,它还与HttpContext耦合在一起
(3) 这里使用了Http Context做缓存,但是如果系统需要使用类似Memcached这样的缓存系统来缓存,Service的代码就需要修改 。(不知道Memcached大神为何物的自己google吧)
2 重构:
(1): 让Service跟Repository解耦 这里我们最先考虑到的应该是通过一个IReository接口,让Service对接口产生依赖,而不具体的类,其实如果仔细一想,就是我们的“依赖反转”原则(依赖与抽象,而不依赖于具体)。于是我们在项目中添加一个IProductRepository的接口,借助IDE,我可以更方便的处理,如图
之后只需要修改我们的ProductService中的代码就好像可以解决这个耦合的问题。
其实再仔细考虑一下,我们还是要在PorductService的构造函数中调用具体的ProductRepository
这样还是有耦合,如果我们需要修改Repository,Service中的代码也还是要修改,要怎么才能不让new ProductRepository出现在这里呢?要不然就传参数进来吧。
不错。于是代码改成这样
这样repository就可以由客户端来指定,这里只负责调用,耦合的问题也就解决了。其实这个就是最简单的“依赖注入”。依赖注入的概念这里就不提了,这个概念说简单很简单,说复杂也很复杂,例如IoC容器,他可以让我们在代码外部通过配置来实例化对象。
(2) :Service中的 GetAllProductsIn 方法耦合的问题,因为我们没有HttpContext的源码,所以利用接口分离实现依赖注入是不可能的。这里引入一个模式叫适配器(Adapter)模式,这里依然不会解释这个模式的具体概念,简单的说就比如我们的插座转换器可以把2个口普通插座转换成3个口的。看下面2张图
适配器模式类图
从GetAllProductsIn方法主要要实现的逻辑来看,我们抽象出这么几个方法,查询缓存,插入缓存,从缓存中移除 3个主要功能。于是如下图。
例子中的类图
根据上面的类图。我们将会把代码改成如下的样子
首先,对Service注入ICacheStorage
其次,修改GetAllProductsIn的方法,绿色注释的部分为修改之前
最后,实现ICacheStorage的方法
到这一步,重构基本就算完成了。这样这个简单的例子就可以更好的被扩展了。
3.再重构与测试
(1) 虽然上面的步骤基本上已经使程序比较面向对象了。但是仔细观察还是发现有一些不满意的地方。比如客户端在调用Service的时候不想使用缓存策略,这段代码就需要修改才实现。要怎么才能符合OCP原则呢?于是再引入一个模式,Null Object模式,非常简单,就是给Service的构造函数传递缓存参数的时候传递一个“null”对象。如图,我们实现一个null的类
(2) 测试 ProductService
关于单元测试,很重要,但是这里不多讨论。(因为我也没有很好的实践J),可以看下面的系列文章
http://www.codeproject.com/KB/cs/autp1.aspx
http://www.codeproject.com/KB/cs/autp2.aspx
http://www.codeproject.com/KB/cs/autp3.aspx
http://www.codeproject.com/KB/cs/autp4.aspx
四、参考文献
《Professional Asp.Net Design Pattens》
出处:http://wjn2010.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利