您现在的位置是:网站首页 -> 程序设计 文章内容
设计模式和反模式-itarticl.cc-IT技术类文章记录&分享
发布时间: 6年前【程序设计】 112人已围观【返回】
简介
在面向对象软件编程的过程中,往往会出现一些普遍存在(反复出现)的问题 。虽然复制粘贴是一种有用的文本编辑操作,但它在代码构建过程中却是灾难性的。
当同样的代码以稍微不同的形式一再出现时,就表示开发人员忽视了抽象。当系统有重复的代码时,对系统进行改动就会变得困难。为此,对反复出现的类似代码进行抽象是很有必要的。
在现代软件开发过程中,人们对于软件设计中普遍存在的问题总结出了一套高效的模式,我们统称其为设计模式。
设计模式提供了一个在架构师和设计人员中捕获知识和经验的机制。它们提供了一种公共语言,可促进对其他地方成功应用的方法的重用,从而为软件项目带来以下方面的好处:风险更低、质量更好且交付时间更短。
而在另一方面,反模式则记录出现错误的情况——对于普遍存在的软件设计缺陷、问题进行总结。
我们将从反模式入手,通过对错误的设计方法总结,延申出正确的设计模式。
反模式
在软件开发过程中,我们常常会因为一些失误或疏忽,导致软件设计存在缺陷,这些或大或小的问题,会在软件不断迭代后,变得越来越明显,最终使得代码的维护变得非常的困难。
以下任何一点特性出现在你的软件中,都意味着你的设计存在缺陷:
- 僵化性:很难对系统进行改动,因为每个改动都会迫使许多对系统其他部分的其他改动。
- 脆弱性:对系统的改动会导致系统中和改动的地方在概念上无关的许多地方出现问题。
- 牢固性:很难解开系统的耦合,使之成为一些在可以在其他系统中重用的组建。
- 不必要的复杂性:设计中包含有不具任何直接好处的基础结构。不必要的重复:设计中包含有重负的结构,而该重复的结构本可以使用单一的抽象进行统一。
- 晦涩性:代码很难阅读、理解。没有很好的表现出意图。
想要避开这些问题,我们必须在设计过程中格外的小心,尽量避开各种反模式。
反模式记录经常重复出现的对效率有负面影响的解决方案。它们通常捕获重构解决方案描述,说明如何更改反模式,以得到更为稳定的解决方案。反模式通常使用模板进行描述,在其中标识症状、结果、根本原因和可能的解决方案。
软件工程中常见的反模式有:
- 上帝对象:在设计的单一部分(某个类)集中了过多的功能。
- 顺序耦合:指这样一些对象,它们的方法必须要按某种特定顺序调用。
- 循环依赖:在对象或软件模块中,直接或间接引入循环依赖。
- 魔数:在算法里直接使用数字,而不解释含义。
- DLL地狱:不同版本DLL所带来的问题,包括DLL可见性和多版本问题,在微软的Windows上尤为突出。
- 抽象倒置:不把用户需要的功能直接提供出来,导致他们要用更上层的函数来重复实现。
- 自我复制:通过不断复制已有代码的模式或代码段进行编码,而非采用抽象。
- 幽灵:指这样一些对象,它们唯一的作用就是把信息传给其它对象。
- 拜物编程:由于对模式的盲目崇拜,在不理解的情况下就使用模式和方法,企图得到好的结果。
避开这些设计误区,能够帮助你写出高效,简洁的代码。
设计原则
与反模式相对的,人们通过对各种问题的不断实践归类,总结出了一套软件设计中的模式。合理的使用这些设计模式,能够提高代码的质量,避开误区。
设计模式采用多种方法解决面向对象设计者经常碰到的问题。它遵循了软件设计的几个基本原则,使得代码高效简洁。
单一职责原则
如果一个类承担的职责过多,就等于把这些职责耦合到了一起。一个职责的变化可能会削弱或者抑制这个类完成其他职能的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。
一个较好的设计是把不同的职责分离到不同的类中。
开放—封闭原则
如果程序中的一处改动会产生连锁反应,导致一系列相关模块的改动,那么设计就具有僵化性。遵循开放—封闭原则设计出的模块具有两个主要特征:
- 对于扩展是开放的。这意味着模块的行为是可扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。我们可以改变模块的功能。
- 对于更改时封闭的。在对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。模块的二进制可执行版本,无论是可链接库、DLL还是so,都无需更改。
遵循这个原则可以使代码获得灵活性、可重用性和可维护性。而它的关键就是对问题和代码进行抽象。开发者们对程序中出现频繁变化的部分做出抽象,同时应该避免对不必要的部分过度的使用抽象。
Liskov替换原则
在面向对象编程过程中,支持抽象以及多态的关键机制之一就是继承。通过继承,我们才创造出实现基类中抽象方法的派生类。而在继承的过程中,我们则要准寻Liskov原则:子类型必须能够替换掉他们的基类型。简单的来说,就是在一个调用基类对象的方法中,用该基类的派生类对象替换该基类对象,方法依旧能够正确执行,我们就认为这一继承准寻Liskov替换原则。
Liskov替换原则是面向对象的基础之一,正式有了这一原则,才使得抽象、多态成为可能。
依赖倒置原则
这一原则大致分为两点:
- 高层模块不应该依赖于底层模块,二者都应该依赖于抽象。
- 抽象不因该依赖于细节。细节应该依赖于抽象。
接口隔离原则
在我们设计接口时,由于个别客户程序的特殊需求,导致我们往接口中加入了其他客户程序不需要的功能,这会导致客户陈旭之间产生不正常并且有害的耦合关系。当一个客户程序要求该接口类进行一个改动时,会影响到其他的客户程序。因此,客户程序应该仅仅依赖他们实际的调用方法。
通常,我们使用委托机制以及多重继承来达到这一要求。
设计模式
设计模式遵循设计准则,能够避开大部分反模式中提到的问题,其大致可以分为三类:
- 创建型模式:抽象了实例化过程,它们帮助一个系统独立于如何创建、组合和表示它的那些对象。
- 结构型模式:涉及如何组合类和对象一伙的更大的结构。
- 行为型模式:分配算法与对象之间的职责,它不仅描述对象或类的模式,还描述两者之间的通信模式。
以下是常见的几个设计模式:创建型模式工厂模式抽象工厂模式单例模式原型模式建造者模式结构型模式适配器模式代理模式行为型模式观察者模式策略模式访问者模式
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结;它描述了某种重复发生的问题,并提供了对应解决某种问题方案的模板.为什么需要设计模式
随着软件需求的日益复杂,软件工程规模和复杂度变得越来越难以掌控,实现一种可以软件标准化,快速化,批量化生产,提高软件开发效率和质量的解决方案尤为重要,而设计模式也由此诞生的.
设计模式优点
- 有利于代码重用,增加代码的可读性及拓展性.
- 让代码更容易被别人理解.
- 保证代码可靠性.
- 弥补语言在某些设计方面的缺陷,提供设计上的一些解决方案.
设计模式缺点
设计模式其实就是一种设计思想,具有一定的针对性,不能理解容易滥用.
对于面向对象而言,使用设计模式,一方面会增加很多新的类,另一方面类和继承等特点使得程序会多很多指针操作来定位函数入口和自身要维护虚拟方法表等额外的工作,从而降低程序运行效率,所以也并不是任何场合都需要使用设计模式.
设计模式对于现代语言优化
设计模式某种意义上是为解决语言本身设计上的缺陷而出现的一些解决方案。不同的语言具有不同的语法特性和设计思想,从而有不同的设计模式;只要存在某些特定的上下文中有似曾相识的美妙的解决方案,那么模式也就出现了。不同语言在使用和实现相同的设计模式也是不一样的,如:在Lisp这样的动态(函数)语言中,由于不需要管理类和对象,不需要解决类给设计上带来的限制,GoF的23种模式中有16种要么用不着,用语言本身提供的机制就可了,要么实现起来要简单得多。比如,Factory和Singleton可以用MetaClass实现,Factory和Command可以用闭包实现,等等;Smalltalk语言本身也提供了MVC等设计模式.
下面主要说一下面向对象编程语言设计模式,函数式编程语言设计模式:
1.函数式编程设计模式:
很多人都认为函数式编程是不需要设计模式的,其实不然,设计模式某种方面来说只是某种特定场合,某种问题的具体解决方案及设计思想的一种经验总结;事实上,技术界在这方面已经做了很多工作,如:Eugene Walingford的模式语言Roundabout和Envoy等,所以函数式编程也是有设计模式的。 oop的设计模式也可以应用于函数式编程语言。具体的设计模式后期补充。
2.面向对象编程设计模式,衡量设计模式的基本原则 :
(1) 单一职责原则:
不要存在多于一个导致类变更的原因。通俗的说,即一个类仅仅负责一项职责。
(2) 里氏替换原则:
全部引用基类的地方必须能透明地使用其子类的对象。
(3) 依赖导致原则:
高层模块不应该依赖低层模块,二者都应该依赖其抽象。抽象不应该依赖细节。细节应该依赖抽象。
(4) 接口隔离原则:
客户端不应该依赖它不须要的接口。一个类对还有一个类的依赖应该建立在最小的接口上。
(5) 迪米特法则:
一个对象应该对其它对象保持最少的了解。
(6) 开闭原则:
一个软件实体如类、模块和函数应该对扩展开放,对改动关闭。
发布时间: 6年前【程序设计】112人已围观【返回】【回到顶端】
很赞哦! (1)
点击排行

站长推荐

猜你喜欢
站点信息
- 建站时间:2016-04-01
- 文章统计:728条
- 文章评论:82条
- QQ群二维码:扫描二维码,互相交流
