设计模式的原则

来源:互联网 发布:折800被淘宝封了 编辑:程序博客网 时间:2024/04/30 01:10
前言 不管做什么事情都要有原则,都要有标准,学习设计模式也是一样,设计模式的原则蕴含在很多设计模式中,它们是从许多设计方案中总结出的指导性原则。面向对象设计原则支持可维护性复用而诞生,来了解一下具体的设计模式原则都是什么。叙述 一、单一职责原则1、是什么: 就一个类而言,应该仅有一个引起它变化的原因。2、怎么来的: 如果一个类承担的职责过多,就等于这个类太“累”,就等于把这些职责耦合在一起,一个职责的变化可能或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。3、怎么用: 一个类只负责一项职责,如果一个类包含多种职责,就把这些职责相互分类。通俗的说就是,如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多余一个的职责,就应该考虑类的职责分离。4、为什么要用: ☞可以降低类的复杂度,一个类只负责一项责,其逻辑肯定要比负责多项职责简单多; ☞提高类的可读性,提高系统的可维护性; ☞变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响 ☞实现高内聚、低耦合的指导方针,做到了易维护、易扩展、易复用、灵活多样。二、开放-封闭原则1、是什么: 软件实体(类、模块、函数等等)应该可以扩展,但是不可修改。对于扩展是开放的,对于修改是封闭的。2、怎么来的: 我们在做系统的时候,都不要指望系统一开始是需求确定,就再也不会变化,这是不现实也不科学的想法,而既然需求使一定会变化的,那么如何在面对需求的变化时,设计的软件可以相对容易修改,不至于说,新需求一来,就要把整个程序推到重来。怎样的设计才能面对需求的改变却可以保持相对稳定,从而使得系统可以在第一个版本以后不断的推出新的版本呢?这时开放-封闭原则就来了。3、怎么用: 设计软件要容易维护又不容易出问题的最好的办法,就是多扩展,少修改。为了满足此原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。无论模块是多么的‘封闭’,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。在我们最初编写代码时,假设变化不会发生,当变化发生时,就立即采取行动,我们就创建抽象来隔离以后发生的同类变化。面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码,这就是“开放-封闭原则”的精神所在。4、为什么要用: 开放封闭原则是面向对象设计的核心所在。是面向对象设计的目标。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护、可扩展、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每一个部分都刻意的进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。三、依赖倒转原则1、是什么: 抽象不应该依赖于细节, 细节依赖于抽象。针对接口编程,不要对实现编程。高层模块不应该依赖底层模块。两个都应该依赖抽象。2、怎么来的: 在面向过程开发时,为了使得常用代码可以复用,常常把这些代码写入函数的程序库,在做新的项目的时候,去调用这些低层的函数就可以了。我们做的项目大多要访问数据库,所以我们就把访问数据库的代码写成了函数,侮次做新项目时就去调用这些函数。这也就叫做高层模块依核低层模块。”我们要做新项目时,发现业务逻辑的高层模块都是一样的,但客户却希望使用不同的数据库或存储信息方式,这时就出现麻烦了。我们希望能再次利用这些高层模块,但高层模块都是与低层的访问数据库绑定在一起的,没办法复用这些高层模块,这就非常糟糕了。而如果不管高层模块还是低层模块,它们都依赖十抽象,具体一点就是接口或抽象类,只要接口是稳定的.那么任何一个的更改都不用担心其他受到彬响,这就使得无论高层模块还是低层模块都可以很容易地被复用。这才是最好的办法。”3、怎么用: 类A的方法依赖类B,如果需要A通过C来实现同样的功能,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。 ☞每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备。 ☞变量的显示类型尽量是接口或者是抽象类。 ☞任何类都不应该从具体类派生。 ☞尽量不要覆写基类的方法。 ☞结合里氏替换原则使用。4、为什么要用: 采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,减少并行开发引起的风险,提高代码的可读性和可维护性。 依赖倒置原则的优点在小型项目中很难体现出来,例如小于10个人月的项目,使用简单的SSH架构,基本上不费太大力气就可以完成,是否采用依赖倒置原则影响不大。但是,在一个大中型项目中,采用依赖倒置原则可以带来非常多的优点,特别是规避一些非技术因素引起的问题。项目越大,需求变化的概率也越大,通过采用依赖倒置原则设计的接口或抽象类对实现类进行约束,可以减少需求变化引起的工作量剧增的情况。人员的变动在大中型项目中也是时常存在的,如果设计优良、代码结构清晰,人员变化对项目的影响基本为零。大中型项目的维护周期一般都很长,采用依赖倒置原则可以让维护人员轻松地扩展和维护。四、里氏代换原则1、是什么: 子类型必须能够替换掉他们的父类型。(一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。在软件里面,把父类都替换成它的子类,程序的行为没有变换。)2、怎么来的: 在依赖倒转原则中,不管是高层模块还是底层模块,他们都依赖于抽象,具体就是接口和抽象类,只要接口是稳定的,那么任何一个的更改都不用担心其他受到影响。为什么依赖了抽象的接口或抽象类,就不怕更改呢?这时就出现了里氏代换原则。3、怎么用: 里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义: ☞子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。 ☞子类中可以增加自己特有的方法。 ☞当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。 ☞当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。4、为什么要用: 里氏代换原则是实现开闭原则的重要方式之一,由于使用父类对象的地方都可以使用子类对象,因此在程序中尽量使用父类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。Summary: 在大多数情况下,这开放-封闭原则、依赖倒转原则、里氏代换设计原则会同时出现,开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段,它们相辅相成,相互补充,目标一致,只是分析问题时所站角度不同而已。五、迪米特法则(最少知识原则)1、是什么: 如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。一个对象应该对其他对象保持最少的了解。2、怎么来的: 类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。因此尽量降低类与类之间的耦合3、怎么用: (1)每一个类都应当尽量降低成员的访问权限 (2)迪米特法则其根本思想是强调了类之间的松耦合。类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。体现了封装的思想。 (3)在类的设计上,只要有可能,一个类应当设计成不变的类。 (4)在对其他类的应用上,一个对象对其他类的对象的应用应该降到最低。 (5)尽量限制局部变量的有效范围。4、为什么要用: 迪米特法则是一种面向对象系统设计风格的一种法则,尤其适合做大型复杂系统设计指导原则。但是也会造成系统的不同模块之间的通信效率降低,使系统的不同模块之间不容易协调等缺点。同时,因为迪米特法则要求类与类之间尽量不直接通信,如果类之间需要通信就通过第三方转发的方式,这就直接导致了系统中存在大量的中介类,这些类存在的唯一原因是为了传递类与类之间的相互调用关系,这就毫无疑问的增加了系统的复杂度。解决这个问题的方式是:使用依赖倒转原则(通俗的讲就是要针对接口编程,不要针对具体编程),这要就可以是调用方和被调用方之间有了一个抽象层,被调用方在遵循抽象层的前提下就可以自由的变化,此时抽象层成了调用方的朋友。六、合成、聚合复用原则1、是什么: 尽量使用合成、聚合,尽量不要使用类继承。2、怎么来的: 很多情况下,使用继承会带来很多麻烦。对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性,所以就优先使用对象合成、聚合,而不是类继承。这就是合成、聚合复用原则的具体体现。3、怎么用: 如果两个类之间是“Has-A”的关系应使用组合或聚合,如果是“Is-A”关系可使用继承。"Is-A"是严格的分类学意义上的定义,意思是一个类是另一个类的"一种";而"Has-A"则不同,它表示某一个角色具有某一项责任4、为什么要用: 优先使用对象的合成聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,井且不太可能增长为不可控制的庞然大物。总结 设计模式的原则虽然不多,但是却深刻的理解到了设计模式的精彩,要认真的去探索每一个原则的精髓,并且要把这些原则运用到我们实际的程序中,让代码更加的简练,更加容易维护,容易扩展和复用。
0 0
原创粉丝点击