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

1. 前言

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

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

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

 

2. 关于“设计”

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

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

 

2.1 面向对象 

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

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

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

 

2.2 抽象与具体

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

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

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

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

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

 

2.3 SOLID五大原则

系统设计的5大原则,简写分别是S、O、L、I、D。

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

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

如果详细分析这5大原则,其实他们都是围绕着“提取抽象、隔离具体”来的。

  • S - 类职责单一原则: 隔离
  • O - 开放封闭原则: 依赖于抽象,隔离具体
  • L - LISKOV原则:抽象
  • I - 接口独立原则:隔离
  • D - 依赖倒置原则:依赖于抽象

 

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. 总结

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

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

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

 

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

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

 

posted @ 2014-04-24 20:53  王福朋  阅读(13541)  评论(7编辑  收藏  举报