• 二十三种设计模式-六大原则


    一、二十三种设计模式

    1、创建型:

    单例模式、工厂模式、抽象工厂模式、原型模式、建造者模式;

     

    2、结构型:

    代理模式,装饰器模式、适配器模式、外观模式、组合模式、享元模式、桥梁模式;

     

    3、行为型:

    策略模式、责任链模式、命令模式、中介者模式、模板方法模式、迭代器模式、访问者模式、观察者模式、解释器模式、备忘录模式、状态模式。

     

    4、三类设计模式的特点:

    二、六大原则

    1、开放封闭(简称开闭)原则

    Open-Close Principle(OCP):一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。目的就是保证程序的扩展性好,易于维护和升级。

    开闭原则被称为面向对象设计的基石,实际上,其他原则都可以看作是实现开闭原则的工具和手段。意思就是:软件对扩展应该是开放的,对修改是封闭的,通俗来说就是,开发一个软件时,应该对其进行功能扩展,而在进行这些扩展时,不需要对原来的程序进行修改。

    好处是:软件可用性非常灵活,扩展性强。需要新的功能时,可以增加新的模块来满足新需求。另外由于原来的模块没有修改,所以不用担心稳定性的问题。

    2、单一职责原则

    Single-Responsibilitiy Principle(SRP):对一个类而言,应该仅有一个引起它变化的原因。如果存在多于一个动机去改变一个类,那么这个类就具有多于一个的职责,就应该把多余的职责分离出去,再去创建一些类来完成每一个职责。

    举个例子:一个人身兼数职,而这些事情相关性不大,甚至有冲突,那他就无法很好的解决这些问题职责,应该分到不同的人身上去做。

    单一职责原则是实现高内聚低耦合的最好方法,没有之一。

     1 class CellPhone:
     2   
     3     def call(string person):
     4       //打电话
     5       pass
     6     def hangup():
     7      //挂断电话
     8         pass
     9 
    10     def sendMessage(string person):
    11     //发送信息
    12         pass
    13     def receiveMessage():
    14     //接受信息
    15         pass

    上面的手机类虽然符合人们对手机的认识,但是实际上却拥有两个不同的职责:打电话、挂断电话和发短信、接受信息,因此引起它变化的原因就有多个,是比较脆弱的设计,应该将两种行为分离。

    3、里氏代换原则

    Liskov Substitution Principle:子类可以扩展父类的功能,但是不能改变父类原有的功能。

    在第一条原则开放封闭原则中,主张“抽象”和“多态”。维持设计的封装性“抽象”是语言提供的功能,“多态”由继承语意实现。因此如何去度量继承关系中的质量?

    答案是:继承必须明确确保超类(父类)所拥有的性质在子类中仍然成立。

    在面向对象的思想中,一个对象就是一组状态和一系列行为的组合体。状态是对象的内在特性,行为是对象的外在特性。LSP表述的就是在同一继承体系中的队形应该具有共同的行为特征。

     1 class bird:
     2     color = ''
     3     weight = ''
     4     def eat():
     5         pass
     6     def fly():
     7         print("fly")
     8         
     9 class chicken(bird):
    10     def fly():
    11         print("can not fly")

    在上述例子中,父类也就是对象鸟有两个行为也就是方法:eat()和fly(),在子类chicken中这两个行为也应该成立,但是现实中chicken是不能飞的,因此chicken中的fly()方法覆盖了父类中的方法。违反了VSP。

    4、依赖倒置原则

    Dependence Inversion Principle(DIP):是一个类与类之间的调用规则。这里的依赖就是代码中的耦合。高层模块不应该依赖底层模块,二者都应该依赖其抽象了;抽象不依赖细节;细节应该依赖抽象。接口编程。

    主要思想就是:如果一个类中的一个成员或者参数成为一个具体的类型,那么这个类就依赖这个具体类型。如果在一个继承结构中,上层类中的一个成员或者参数为一个下层类型,那么就是这个继承结构高层依赖底层,就要尽量面向抽象或者接口编程。

    举例:存在一个Driver类,成员为一个Car对象,还有一个driver()方法,Car对象中有两个方法start()与stop()。显然Driver依赖Car,也就是说Driver类调用了Car类中的方法。但是当增加Driver类对于Bus类的支持时(司机有需要开公交车),就必须更改Driver中的代码,就破坏了开放封闭原则。根本原因在于高层的的Driver类与底层的Car类仅仅的耦合在一起的。解决方法之一就是:对Car类和Bus类进行抽象,引入抽象类Automoble。而Car和Bus则是对Automobile的泛化。

    经过这样的改造发现,原本的高层依赖底层,变成了高层与底层同时依赖抽象。这就是依赖倒转原则的本质。

    5、接口隔离原则

    接口隔离原则(Interface Segregation Principle):用于恰当的划分角色和接口,具有两种含义:1、用户不应该依赖它不需要的借口;2、类间的依赖关系应该建立在最小的的接口上。

    将这两个定义概括为一句话:建立单一接口,代替庞大臃肿的接口。通俗来说就是:接口尽量细化,同时保证接口中的方法尽量的少。一个接口中包含太多的行为时,会导致它们与客户端的不正常依赖关系,要做的就是分离接口,从而实现解耦。

    回到上述的单一职责原则,要求行为分离接口接口细化,感觉有些相同。但实际上,单一职责原则要求类与接口的职责单一,注重的是职责,没有要求接口尽量的少。

    在接口隔离原则中,要求尽量使用多个专门的接口。专门的接口也就是提供给多个模块的接口。提供给几个模块就应该有几个接口,而不是建立一个臃肿庞大的接口,所有的模块都可以访问。

    但是接口的设计是有限度的。接口的设计粒度越小系统越灵活,这是事实,但是接口太多这也就使得结构复杂,维护难度大。因此实际中,怎样把握就靠开发的经验和常识了。

    6、迪米特原则

    Law of Demeter(最小知识原则):一个对象应该对其他对象有最少的了解。通俗来说就是,一个类对自己需要耦合或者调用的类知道的最少,你类内部怎么复杂,我不管,那是你的事,我只知道你有那么多公用的方法,我能调用。

    迪米特原则不希望类与类之间建立直接的接触。如果真的需要有联系,那么就通过它们的友元类来传达。举例来说:你需要买房子了,现在存在三座合适的楼盘A,B,C,但是你不必直接去楼盘买楼,而是在售楼处去了解情况。这样就减少了你(购房者)与楼盘两个类之间耦合。

    但是应用迪米特原则很可能会造成一个后果:系统会存在大量的中介类,这些类(如上面的售楼处类)之所以存在是为了传递类之间的相互调用关系,这就一定会程度上增加了系统的复杂度。

    迪米特原则核心观念就是:类间解耦,弱耦合。

    三、示例代码

    python实现23种设计模式示例代码地址如下

    Github链接:https://github.com/weilanhanf/PythonDesignPatterns

  • 相关阅读:
    平衡二叉树(AVL Tree)
    算法分析
    稳定匹配
    Python读取不同文件夹下的图片并且分类放到新创建的训练文件夹和标签文件夹
    java构造函数也可以用private开头
    基于slf4j的log4j实战
    javascript权威指南第6版学习笔记
    hadoop之wordCount程序理解
    java 基本类型和包装类的比较
    设计模式之工厂模式,单例模式,门面模式
  • 原文地址:https://www.cnblogs.com/welan/p/9005019.html
Copyright © 2020-2023  润新知