设计模式之六大原则

     大话设计学习也一段时间了,每一个设计模式都设计到六大原则,只不过是涉及多少不一样。下面简答介绍一下这六大原则 。


一 单一职责原则(SRP Single Responsibility Principle


1.定义:


就一个类而言,应该仅有一个引起它变化的原因。


2.问题由来:


一个类负责两个不同的职责,当一个职责的需求发生变化需要修改类的时候,可能会导致另一个职责发生故障。为了解决编程中一个功能发生故障而导致另其他功能发生故障的问题。 


3.理解:


如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。手机的职能很多,但是每个功能都不如那些单独具有这些功能的东西。


二 开放—封闭原则(OCP  Open Close Principle)


1.定义:


软件实体(类、模块、函数等)应该可以可扩展,但是不可以修改。


2.问题由来:


在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。


3.理解:


    开发封闭原则有两个特征,一是对于扩展是开放的(open for extension),二是对于更改是封闭的(closed for modification)。设计软件既容易修改又不容易出问题的最好的办法就是多扩展少修改。程序的设计应该可以面对需求的改变时可以保持相对稳定,从而使得系统可以在第一个版本以后不断推出新的版本。设计类时尽量让这个类足够好,写好了尽量就不去修改了,如果有了新需求,增加一些类,原来的代码能不动就不动。在我们最初编写代码时,假设变化不会发生。当变化发生时,创建抽象来隔离以发生的同类变化。


    以大话中的例子来说,如果要增加一个算法,上面的这个如果增加一个算法功能,就得修改原来这个类,这就违背了开发封闭的原则,如果像下面这个增加一个抽象的运算类,通通过一些面向对象的手段如继承、多态等来隔离具体加减法与client耦合,我们再增加算法子类就可以面对需求。

        设计模式之六大原则_第1张图片

三 依赖倒转原则(DIP Dependence Inversion Principle


1.定义:


       高层模块不应该依赖低层模块。两个都应该依赖抽象。

       抽象不应该依赖细节,细节应该依赖抽象。


2.问题由来:


    类A直接依赖类B,假如要将类A改为依赖类C,则必须通过修改类A的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B和类C是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。


3.理解:


    为了解决以上问题将类A修改为依赖接口I,类B和类C各自实现接口I,类A通过接口I间接与类B或者类C发生联系,则会大大降低修改类A的几率。依赖倒转其实就是可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖所有的依赖关系都是终止于抽象类或是接口inajiushi面向对象的设计,反之就是过程化的设计。依赖倒转原则说白了就是对接口编程,不要对实现编程。无论主板、CPU、内存、硬盘都是在针对接口设计的,如果针对实现来设计,内存就要对应到具体的某个品牌的主板,就会出现换内存需要把主板也换掉的尴尬。


软件也是一样,我们做的项目大多数要访问数据库,所以我们就把访问数据库的代码写成了函数,每次做新项目是就去调用这些函数,这也叫做高层模块依赖低层模块。但是我们做新项目时,发现业务逻辑的高层模块都是一样的,但客户却希望使用不同的数据库或存储信息方式,这事就会出现麻烦。我们希望能再次利用这些高层模块,但是高层模块都是与低层的访问数据库绑定在一起,没办法复用这些高层模块。所以应该依赖与抽象。

           设计模式之六大原则_第2张图片

         设计模式之六大原则_第3张图片

四 里氏代换原则(LSP Liskov Substitution Principle


1.定义:


   子类型必须能够替换掉它们的父类型。


2.问题由来:


    有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。


3.理解


    类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且察觉不出父类对象和子类对象的区别,就是说,在软件里面,把父类都替换成它的父类,程序的行为没有变化,像大话中关于继承的讲解,子类继承了父类,所以子类可以以父类的身份出现。因为有了这个原则,使得继承复用成为了可能,只有当子类可以替换掉父类,软件单位的功能不受影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。


五 迪米特法则(LOD Law Of Demeter


1.定义:


    如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。让路过其中一个类需要调用另一个类的某一个类的某一个方法的话,可以通过第三者转发这个调用。


2.问题由来:


    类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。


3.理解:


    这个法则强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限,一个类包装好自己的private状态,需要让别的字段或行为就不要公开。它的根本思想是强调了类之间的松耦合。类之间的耦合越弱,越有利于复用,一个处在若耦合的类被修改,不会对有关系的类造成波及。这样即使IT部门换了人还是可以找IT部主管。


六 合成/聚合复用原则


1.定义:


    尽量使用合成/聚合,尽量不要使用类继承。


2.问题由来:


    在刚开始学会用面向对象的继承时,感觉既新颖又功能强大,所以只要可以用就都用上继承,但事实上很多情况用继承就会带来麻烦。


3.理解:


    聚合表示一种弱的 ‘拥有关系’,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;组合则是一种强的 ‘拥有’关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样;

             设计模式之六大原则_第4张图片

     按大话上的手机品牌和手机功能的例子来说,优先使用继承,这样如果增加很多功能或是手机品牌就太麻烦了。

     设计模式之六大原则_第5张图片

 如果使用合成/聚合原则就简单多了,分为手机品牌抽象类和手机软件抽象类。让不同的品牌和功能都分别继承于它们,这样要增加的新的品牌和功能都不会影响其他的类了。

设计模式之六大原则_第6张图片

 对象的继承关系是在编译时就定义好了的,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常密切的依赖关系,以至于父类实现中的任何变化必然会导致子类更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。


七 总结


 设计模式的六大原则贯穿始终,需要我们灵活的运用它们,相信在以后的学习中会理解的更深刻一些.         



你可能感兴趣的:(设计模式,编程,继承,面向对象)