转载请标注来源:http://www.cnblogs.com/charles04/p/8935130.html
设计模式--开篇
0、目录
- 引言
- 面向对象的四大特征
- 面向对象的六大原则
- 设计模式的分类
1、引言
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。
2、面向对象的四大特征
面向对象(Object Oriented, OO)是设计模式的根源,在进行设计模式的讲解之前,先让我们简单回顾下面向对象的相关知识。
从大一接触C++开始,提到面向对象,就不得不提到面向对象的四大特征:封装,继承,多态。
(1). 抽象
抽象是OO思想的精髓,是继承和多态的基础。抽象告诉我们,不关注对象的内部实现细节,而只关心对外提供的功能。抽象的结果是一组或多组有内部联系的接口的组合。接口和抽象类都是面向对象中抽象的具体表现形式。
(2). 封装
封装是指,将数据属性信息和对数据的操作进行打包,变成一个不可分割的实体(类)。其中属性信息就是参数,对数据的操作又称之为方法,方法其实也是对数据更低维度的封装。通过封装,可以界定外部的访问权限,保障数据的安全性,而且简化了外部的调用逻辑,使类更加具有普适性。
(3). 继承
继承是指从已有的类中派生出子类,子类不仅可以继承父类的属性和方法,还可以根据自身的特点,拓展出新的行为,保障了代码的复用性。这里的父类有抽象的封装的概念,而子类有多态的概念,读到这里的人,可以细细品味下。
(4). 多态
多态是指同一实体具有多种形式。OO中,多态一般分为静态多态和动态多态。静态多态是指方法名相同而参数不同的同名函数的情况;而多态实际上就是泛型,OO中通常通过接口和抽象类实现泛型,多态通常会表现在继承类的重载方法和接口的实现上。是面向对象的一个重要组成部分。
3、面向对象的六大原则
介绍完面向对象的四大特性之后,再来简单介绍下面向对象的六大原则,具体如下:
3.1. 单一职责原则(Single Responsibility Principle, SRP)
(1). 定义
一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。通俗的说,即一个类只负责一项职责。
在软件系统中,一个类(大到模块,小到方法)承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关实践经验。
3.2. 开闭原则(Open Close Principle)
一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
任何软件都需要面临一个很重要的问题,即它们的需求会随时间的推移而发生变化。当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。随着软件规模越来越大,软件寿命越来越长,软件维护成本越来越高,所以,为了使程序的扩展性好,易于维护和升级,满足开闭原则是十分重要的。
为了满足开闭原则,需要对软件架构进行抽象化设计,抽象化是开闭原则的关键。想要达到这样的效果,我们需要使用到接口和抽象类。
3.3. 里氏替换原则(Liskov Substitution Principle)
所有引用基类(父类)的地方必须能透明地使用其子类的对象
里氏代换原则由2008年图灵奖得主、美国第一位计算机科学女博士,麻省理工大学的Barbara Liskov教授在1988年提出的。
里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。实现"开-闭"原则的关键步骤就是抽象化。在具体操作的时候,尽量把父类设计为抽象类或者接口,让子类继承父类或实现父接口,并实现在父类中声明的方法,运行时,子类实例替换父类实例,我们可以很方便地扩展系统的功能,同时无须修改原有子类的代码,增加新的功能可以通过增加一个新的子类来实现。
由此可见,里氏代换原则是开闭原则的具体实现手段之一。
3.4. 依赖倒转原则(Dependence Inversion Principle)
抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。
依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。在引入抽象层后,系统将具有很好的灵活性,在程序中尽量使用抽象层进行编程,而将具体类写在配置文件中,这样一来,如果系统行为发生变化,只需要对抽象层进行扩展,并修改配置文件,而无须修改原有系统的源代码,在不修改的情况下来扩展系统的功能,满足开闭原则的要求。
3.5. 接口隔离原则(Interface Segregation Principle)
使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
这个原则又可以叫做角色隔离原则。这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。当一个接口太大时,我们需要将它分割成一些更细小的接口,使用该接口的客户端仅需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
3.6. 迪米特法则(最少知道原则)(Demeter Principle)
一个软件实体应当尽可能少地与其他实体发生相互作用。
迪米特法则来自于1987年美国东北大学(Northeastern University)一个名为"Demeter"的研究项目。迪米特法则又称为最少知识原则(LeastKnowledge Principle, LKP);
如果一个系统符合迪米特法则,那么当其中某一个模块发生修改时,就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。迪米特法则要求我们在设计系统时,应该尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。
在将迪米特法则运用到系统设计中时,要注意下面的几点:在类的划分上,应当尽量创建松耦合的类,类之间的耦合度越低,就越有利于复用,一个处在松耦合中的类一旦被修改,不会对关联的类造成太大波及;在类的结构设计上,每一个类都应当尽量降低其成员变量和成员函数的访问权限;在类的设计上,只要有可能,一个类型应当设计成不变类;在对其他类的引用上,一个对象对其他对象的引用应当降到最低。
4、设计模式的分类
通过上面的回顾,相信已经对面向对象有了比较深的了解。接下来会重点介绍下面比较常用的一些设计模式。总体来说设计模式分为三大类:
共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
敬请期待。