您的位置:首页 > 其它

你为什么总是学不会设计模式?

2015-04-18 19:24 302 查看




1. 前言

设计模式——最熟悉的陌生人。

很多人应该都有这种感受,早就知道设计模式,也能随口说出几种,但是不知道每种是怎么回事。或者说只知道工厂模式等几个常用,简单的。估计那也是靠记忆,而不是真正的理解。

我也有这种亲身体会,在好几年之前就知道设计模式。之前也一直抽时间学,但总是学了就忘。而且学习过程很枯燥,完全是背诵式的记忆那些类图,不是真正的理解,更别提应用了。

 


2. 关于“设计”

设计,就是为了更好的应对变化。没毕业时候不知道软件系统怎么会有变化,但是工作之后慢慢就会发现,变化,那叫一个天马行空。。。

一提到“设计”,大部分人可能会直接想到设计模式,而且是23种设计模式。其实这是错误的。其实学会设计、应用设计,应该分为四个层次:

 

2.1 面向对象 

首先要了解面向对象,什么是面向对象?什么是封装、继承和多态,以及三个特点的表现形式。基础很重要。

要想充分了解面向对象,三个特点,最好还是按部就班的参考一本权威书籍,看看书上说的你是不是真的理解。看看继承和多态的表现形式你是否都知道。

如果没按部就班看过书,就不要以为自己都会了。借用某相声演员一句话:“你以为你以为的就是你以为的?”。。。

 

2.2 SOLID五大原则

系统设计的5大原则,简写分别是S、O、L、I、D。
S - 类职责单一原则: 即职责划分要清晰,不同职责的不要搅和在一起。每个类应该只有一个让他发生改变的原因。
O - 开放封闭原则: 对扩展开发,对修改封闭。即如果系统要变化,就去扩展、新增新类,不要修改现有的类。
L - LISKOV原则: 子类应该能充分覆盖父类,并且让使用者分不出差别。
I - 接口分离原则:每个接口只管一个功能,不要出现“胖接口”。增加功能时,要加接口,而不是改接口
D - 依赖倒置原则:具体应该依赖于抽象,而不是抽象一来于具体,即低层要依赖于高层。

对于以上5大原则,此处不详细解释,有兴趣的可以查阅《你必须知道的.net》第二版,里面讲的非常详细。

如果详细分析这5大原则,其实他们都是围绕着“提取抽象、隔离具体”来的。
S - 类职责单一原则: 隔离
O - 开放封闭原则: 依赖于抽象,隔离具体
L - LISKOV原则:抽象
I - 接口独立原则:隔离
D - 依赖倒置原则:依赖于抽象

S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写。
SRPThe Single Responsibility Principle 单一责任原则
OCPThe Open Closed Principle 开放封闭原则
LSPThe Liskov Substitution Principle里氏替换原则
DIPThe Dependency Inversion Principle依赖倒置原则
ISPThe Interface Segregation Principle接口分离原则
Steve Smith在5月份的微软TechED 2009上有个SOLIDify Your ASP.NET MVC的讲座, derick.bailey的SOLID
Development Principles – In Motivational Pictures很好的解释了SOLID原则。

单一责任原则: 

当需要修改某个类的时候原因有且只有一个(THERE SHOULD NEVER BE MORE THAN ONE REASON FOR A CLASS TO CHANGE)。换句话说就是让一个类只做一种类型责任,当这个类需要承当其他类型的责任的时候,就需要分解这个类。 

 



开放封闭原则 

软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的。这个原则是诸多面向对象编程原则中最抽象、最难理解的一个。



 

里氏替换原则 

当一个子类的实例应该能够替换任何其超类的实例时,它们之间才具有is-A关系 


  
依赖倒置原则
1. 高层模块不应该依赖于低层模块,二者都应该依赖于抽象 

2. 抽象不应该依赖于细节,细节应该依赖于抽象 





接口分离原则 

不能强迫用户去依赖那些他们不使用的接口。换句话说,使用多个专门的接口比使用单一的总接口总要好。 





这几条原则是非常基础而且重要的面向对象设计原则。正是由于这些原则的基础性,理解、融汇贯通这些原则需要不少的经验和知识的积累。上述的图片很好的注释了这几条原则。

2.3抽象与具体

如何更好的解决“变化”问题?答案是“提取抽象、隔离具体”。 

什么是“抽象”? 抽象就是不变的东西,一个数据表的操作,总会有增删改查,把他们作为接口,这是不变的。

什么是“具体”? 具体是实际执行的,一个数据表的增删改查,用sqlserver、access还是oracle?可能会有变化。

我们应该依赖于抽象编程,而不是依赖于具体编程。应该把程序中的共性抽象出来,并且把具体实现的部分隔离开来,让他们都依赖于抽象,并且互不影响。这其实就是设计。

只有理解了“抽象”、“具体”、“隔离”这几个词儿,你才能真正理解设计模式。否则就别指望。

 

2.4 设计模式

最后才是设计模式,设计模式其实是一些工具而已。

是“术”,不是“道”。如果你不明白以上那些“道”,而直接去学“术”,肯定是学一次忘一次。

在看每个设计模式的时候,你都要去向着这个方向去思考:它是不是提取了抽象、分离了具体、依赖于抽象、封装了具体? 这样一来,你就会明白了。

 


3 例子:工厂模式

工厂模式在设计模式中分三种:简单工厂、工厂方法和抽象工厂,其实这三种对应了不同的抽象程度。 下面简单分析前两种。

3.1 简单工厂:



看上图,很明显是“提取抽象,分离具体”。将数据操作的接口提取出来,交给不同的实现类来实现。

工厂类返回的是IDBHelper接口,即客户端会调用IDBHelper接口,而不需要关心具体实现,这就是“依赖于抽象,而不是依赖于具体”。

还符合“开放封闭原则”,例如现在又要用DB2数据库,那么再加一个实现类就行,无需改其他地方。客户端也不会察觉后台的变化。这就是:对扩展开放,对修改封闭。

 

简单工厂之所以叫“简单”,是因为它的工厂类还依赖于数据操作实现类,这违反了“依赖倒置原则”,那么该怎么办呢?

 

3.2 工厂方法:

上文说了,简单工厂类依赖与数据操作实现类,当前有3个实现类,那么工厂类肯定需要判断,免不了有if else或者swicth case语句,

switch (type)
{
case "sqlserver":
return new SQLDBHelper();
case "oracle":
return new OracleDBHelper();
case "access":
return new AccessDBHelper();
default:
throw new Exception("type参数错误");
}


而这些语句,就是设计模式重点要改进的地方。

如何让工厂类不依赖于数据操作实现类? 答案还是“提取抽象,分离具体实现”。



 

将工厂类的具体职责抽象出来,然后分离一些实现类,分别实现各自的功能。

 


4. 总结

学设计模式不容易,需要熟悉语言、面向对象、理解设计原则。。。。即便是都看会了,理解了,到了应用又是个麻烦事儿。

有一位大牛说过:《设计模式》这本书,我们要像字典一样经常拿出来翻翻看看,而不是通篇看完就算了。

可见,它需要我们长期的“学习 - 应用 - 总结 - 学习”,才能更好的理解。

 

另外,我感觉在系统设计中,也没有必要非得去套用设计模式,只要符合设计原则,符合开发、运行效率,怎样设计都行,不要为了用而用,滥用不如不用。

话又说回来,还是对设计大原则,对“道”的理解。

5、参考文献

http://www.cnblogs.com/wangfupeng1988/p/3687346.html

http://www.cnblogs.com/shanyou/archive/2009/09/21/1570716.html
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: