设计模式 从入门到住院 new
2020-10-20 10:00:13 0 举报
AI智能生成
设计模式
作者其他创作
大纲/内容
前言
产生背景
概念与意义
基本要素
模式名称
每一个模式都有自己的名字,通常用一两个词来描述,可以根据模式的问题、特点、解决方案、功能和效果来命名。模式名称(PatternName)有助于我们理解和记忆该模式,也方便我们来讨论自己的设计。
问题
问题(Problem)描述了该模式的应用环境,即何时使用该模式。它解释了设计问题和问题存在的前因后果,以及必须满足的一系列先决条件。
解决方案
模式问题的解决方案(Solution)包括设计的组成成分、它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合,所以解决方案并不描述一个特定而具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象的 组合)来解决这个问题。
效果
描述了模式的应用效果以及使用该模式应该权衡的问题,即模式的优缺点。主要是对时间和空间的衡量,以及该模式对系统的灵活性、扩充性、可移植性的影响,也考虑其实现问题。显式地列出这些效果(Consequence)对理解和评价这些模式有很大的帮助。
分类和功能
分支主题
23种设计模式简介
设计模式产生目的
耦合性
耦合度,是对模块之间关联的度量
内聚性
类型(由低到高)
偶然内聚性(Coincidental cohesion,最低)
逻辑内聚性(Logical cohesion)
时间内聚性(Temporal cohesion)
程序内聚性(Procedural cohesion)
联系内聚性/信息内聚/通信内聚(Communicational cohesion)
依序内聚性/顺序内聚(Sequential cohesion)
功能内聚性(Functional cohesion,最高)
可维护性
可扩展性
当需要增加新的功能,非常的方便
重用性
相同功能代码.,不用多次编写
灵活性
可读性
编程规范性,便于其他程序员的阅读和理解
7大设计模式原则解析
开闭原则(Open Closed Principle,OCP)
定义
软件实体 应该 对扩展开放,对修改封闭
系统进行扩展是被鼓励的,对现有系统代码进行修改是不被支持的。
当软件有新的需求变化的时候,只需要通过对软件框架进行扩展来适应新的需求,而不是对框架内部的代码进行修改。
软件实体包含部分
项目中划分出的模块
抽象和类
方法
作用
对软件测试的影响
软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。
可以提高代码的可复用性
在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性
粒度越小,被复用的可能性就越大。
可以提高软件的可维护性
遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。
举栗子
小结
通过“抽象约束、封装变化”来实现开闭原则。
通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中
前瞻性和预见性
对需求的变更保持前瞻性和预见性,就可以使抽象具有更广泛适用性,设计出的软件架构就能相对稳定。
软件需求中易变的细节,通过从抽象派生出实现类来扩展。
因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。
而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变化时,只需要根据需求重新派生一个实现类来扩展就可以了。
代表设计模式
装饰者模式
单一职责原则( Single Responsibility Principle, SRP )
定义
一个类应该有且仅有一个引起它变化的原因,该类的职责是唯一的,且这个职责是唯一引起其他类变化的原因,否则类应该被拆分(There should never be more than one reason for a class to change)。
作用
降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
系统解耦合
提高类的可读性。复杂性降低,自然其可读性会提高。
提高系统的可维护性。可读性提高,那自然更容易维护了。
变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。
举栗子
SingleResponsibility
SingleResponsibility2
SingleResponsibility3
小结
将不同的职责封装到不同的类或者模块中。
当有新的需求将现有的职责分为颗粒度更小的职责的时候,应该及时对现有代码进行重构。
当系统逻辑足够简单,方法足够少,子类够少或后续关联够少时,也可以不必严格遵循SRP原则,避免过度设计、颗粒化过于严重。
只有类中方法数量足够少,可以在方法级别保持单一职责原则;
代表设计模式
迭代器模式
里氏替换原则(Liskov Substitution Principle,LSP)
继承
优点
代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;
提高代码的重用性;
子类可以形似父类,但又异于父类;
提高代码的可扩展性,很多开源框架的扩展接口都是通过继承父类来完成的;
提高产品或项目的开放性。
缺点
继承是侵入性的。只要继承,就必须拥有父类的所有属性和方法;
降低代码的灵活性。子类必须拥有父类的属性和方法;
增强了耦合性。当父类的常量、变量和方法被修改时,需要考虑子类的修改,而且在缺乏规范的环境下,这种修改可能带来非常糟糕的结果—— 大段的代码需要重构。
定义
如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2 时,程序P的行为没有发生变化,那么类型 S 是类型 T 的子类型。
所有引用基类的地方必须能透明地使用其子类的对象。
作用
避免系统继承体系被破坏,为良好的继承定义了一个规范。
是实现开闭原则的重要方式之一。
它克服了继承中重写父类造成的可复用性变差的缺点。
它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
举栗子
小结
子类可以实现父类的抽象方法,但是不能覆盖父类的非抽象方法;
子类中可以增加自己特有的方法;
当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松;
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
如果子类不能完整地实现父类的方法,或者父类的一些方法在子类中已经发生畸变(鸵鸟是鸟不会飞),则建议断开继承关系,采用依赖,聚合,组合等关系代替继承。
依赖倒置原则(Dependency Inversion Principle,DIP)
依赖方式
依赖正置:
类之间依赖是实现类间的依赖,面向实现变成;
依赖倒置:
面向接口编程;
定义
High level modules should not depend upon low level modules. Both should depend up on abstractions. Abstractions should not depend upon details. Details should depend upon abstractions。
高层模块不应该依赖低层模块,二者都应该依赖其抽象;
低层模块
高层模块
抽象不应该依赖细节;
细节应该依赖抽象 ;
作用
减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性;
举栗子
原始
改进后
小结
面向接口编程,使用接口或者抽象类制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
变量的表面类型,尽量是接口或者抽象类;
任何类都不应该从具体类派生;
尽量不要覆写基类(抽象类)的实现的方法;
结合里氏替换原则使用;
它是实现开闭原则的重要途径;
对扩展开放,对修改关闭;
代表设计模式
工厂模式
接口隔离原则(Interface Segregation Principle,ISP)
定义
Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依 赖它不需要的接口。)
The dependency of one class to another one should depend on the smallest possible interface. (类间的依赖关系应该建立在最小的接口上。)
作用
避免接口过于臃肿
举栗子
小结
接口要尽量小
根据接口隔离原则拆分接口时,首先必须满足单一职责原则。
接口要高内聚
提高接口、类、模块的处理能力,减少对外的交互。
要求在接口中尽量 少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也就越 少,同时也有利于降低成本。
定制服务
单独为一个 个体提供优良的服务,减少可能引起的风险。
做系统设计时也需要考虑对系统之间或模块之间的接口采用定制服务。
接口设计是有限度的
接口的设计粒度越小,系统越灵活,这是不争的事实。
已经被污染了的接口,尽量去修改,若变更的风险较大,则采用适配器模式进行转化 处理;
灵活的同时也带来了结构 的复杂化,开发难度增加,可维护性降低 , 了解环境 , 拒绝盲从。每个项目或产品都有特定的环境因素,环境不同,接口拆分的标准就不同。深入了解业务逻辑,最好的接口设 计就出自你的手中!
迪米特法则(Law of Demeter,LOD)/ 最少知识原则(Least Knowledge Principle,LKP)
定义
一个对象应该对其他对象有最少的了解 ;
Talk only to your immediate friends and not to strangers。(只与直接的朋友通信。)
作用
降低了类之间的耦合度,提高了模块的相对独立性。
由于亲合度降低,从而提高了类的可复用率和系统的扩展性。
[object Object]
举栗子
小结
在类的划分上,应该创建弱耦合的类。类与类之间的耦合越弱,就越有利于实现可复用的目标。
在类的结构设计上,尽量降低类成员的访问权限。
在类的设计上,优先考虑将一个类设置成不变类。
在对其他类的引用上,将引用其他对象的次数降到最低。
不暴露类的属性成员,而应该提供相应的访问器(set 和 get 方法)。
谨慎使用序列化(Serializable)功能。
代表
外观模式
中介者模式
合成复用原则(Composite Reuse Principle,CRP)又叫组合/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)
定义
当要扩展类的功能时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
如果要使用继承关系,则必须严格遵循里氏替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。
作用
防止类的体系庞大
通过将已有的对象纳入新对象中,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用。
举栗子
小结
当类与类之间的关系是"Is-A"时,用继承;当类与类之间的关系是"Has-A"时,用组合。
Is-A
这种事物(绵羊)是那种事物(羊)中的一个种类。
Has-A
这种事物(羊毛)隶属于那种事物(绵羊),是它的一个部分、部件。
代表设计模式
桥接模式
总结
(1)单一职责原则要求实现类要职责单一;
(2)里氏替换原则要求不要去破坏继承系统;
(3)依赖倒置原则要求面向接口编程;
(4) 接口隔离原则要求在设计接口的时候要精简单一;
(5) 迪米特法则要求要降低耦合;
(6)开闭原则是总纲,要求对扩展开发,对修改关闭。
23种设计模式分类
创建型模式
描述
是将对象的创建与使用分离.
作用
是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”。
这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。
分类(5种)
类创建型模式
工厂方法(FactoryMethod)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。
对象创建型模式
单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
结构型模式
描述
如何将类或对象按某种布局组成更大的结构。
它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。
作用
分类(8种)
对象结构型模式
代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现的,从而降低了抽象和实现这两个可变维度的耦合度。
装饰(Decorator)模式:动态地给对象增加一些职责,即增加其额外的功能。
外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。
组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
类结构型模式
适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
行为型模式
描述
用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,它涉及算法与对象间职责的分配。
按照其显示方式的不同,行为型模式可分为类行为模式和对象行为模式.
类行为型模式使用继承关系在几个类之间分配行为,主要通过多态等方式来分配父类与子类的职责;
对象行为型模式则使用对象的组合或聚合关联关系来分配行为,主要是通过对象关联等方式来分配两个或多个类的职责。
由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”所以对象行为模式比类行为模式具有更大的灵活性。
作用
分类(11种)
类型为模式
模板方法(Template Method)模式:定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。
对象行为模式
策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。
观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。
中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
GOF 23种设计模式
单例设计模式
定义
指一个类只有一个实例,且该类能自行创建这个实例的一种模式。
特点
单例类只有一个实例对象;
该单例对象必须由单例类自行创建;
单例类对外提供一个访问该单例的全局访问点;
Q : 有几种?
8种
饿汉式 2种
静态常量
静态代码块
懒汉式 3种
线程不安全
线程安全,同步方法
线程安全,同步代码块
双重检查
静态内部类
枚举
优点
由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁地创建,销毁时,而且创建或销毁时性能又无法优化.
由于单例模式只生成一个实例,所以减少了系统的性能开销,当一个对象的产生需要 比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一 个单例对象,然后用永久驻留内存的方式来解决(在Java EE中采用单例模式时需要注意JVM 垃圾回收机制)。
单例模式可以避免对资源的多重占用,例如一个写文件动作,由于只有一个实例存在 内存中,避免对同一个资源文件的同时写操作。
单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单 例类,负责所有数据表的映射处理。
缺点
使用场景
需要频繁的进行创建和销毁的对象;
创建对象时耗时过多或耗费资源过多,但又经常用到的对象;
工具类对象;
频繁访问数据库或文件的对象。
工厂方法模式
抽象工厂模式
模版方法模式
建造者模式
代理模式
原型模式
中介者模式
命令模式
责任链模式
装饰模式
策略模式(Strategy Pattern)
定义
一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
体现原则
把变化的代码从不变的代码中抽离出来
针对接口编程而不是具体类(定义了策略接口)
多用组合/聚合,少用继承(客户通过组合方式使用策略)
优点
算法可以自由切换。
避免使用多重条件判断。
扩展性良好。
缺点
策略类会增多。
所有策略类都需要对外暴露。
适配器模式
迭代器模式
组合模式
观察者模式
门面模式
备忘录模式
访问者模式
状态模式
解释器模式
享元模式
桥梁模式
空对象模式
规格模式
对象池模式
雇工模式
黑板模式
空对象模式
杂谈
UML
UML中的类的关系图
分支主题
类图六大关系
依赖关系(dependency)
类中用到对方
类的成员属性
方法的返回类型
方法接收的参数类型
方法中使用到
泛华/继承(generalization)
依赖关系的特例
实现(implementation)
依赖关系的特例
关联(association)
依赖关系的特例
关联具有导航性 : 单向/双向关系;
栗子
聚合(aggregation)
是关联关系的特例
整体与部分的关系,整体与部分可以分开.
栗子
组合(composition)
是关联关系的特例
是整体与部分的关系,整体与部分不可以分开.
栗子
参考
<<设计模式之禅>> 秦小波
网站 : http://c.biancheng.net/view/1317.html
各大CSDN博主
By 萧曵
收藏
0 条评论
下一页