OOAD-设计模式(二)之GRASP模式与GOF设计模式概述
一、GRASP模式(通用责任分配软件模式)概述
1.1、理解责任
1)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为、数据、对象的创建等 知道责任——表示知道什么 行为责任——表示做什么 责任=知道责任+行为责任
2)知道责任与行为责任
知道责任: 了解私有封装数据 了解关联的对象 了解能够派生或计算的事物 行为责任: 如何完成对象初始化 如何执行一些控制行为
3)责任的理解
责任不是类的方法,类的方法用于【实现行为责任】。责任更可以理解成是系统应提供的一个业务功能 责任的分配可使用顺序图或协作图来表达(之后会讲到UML中的图) 面向对象设计过程就是将责任分配给对象的过程
4)举例说明
在一个销售业务中,存在一个交费行为(业务功能),可将它识别为一个责任: 行为责任表示交费的行为,需要创建一的个付款记录对象Payment。 知道责任必须知道付款记录类Payment,知道如何记录及计算Payment类中的数据。
二、GRASP模式的分类
作用/则重点:完成责任分配(以及分配责任的时候需要注意的点) GRASP模式也是遵循基本的设计原则的(也就是说GRASP模式是在基本设计原则基础之上建立的)。
2.1、Information Expert(信息专家)
谁能够在某方面具有完整的信息,足以实现某个责任,就将责任分配给这个类,这个类即所谓的信息专家。 总结为"谁知道谁负责" 1.要知道的责成内容是什么 2.完成这个责任需要哪些信息 3.哪些对象拥有这些完成的信息 4.分配责任的同时不能违反基本的设计原则
例如:在购物车系统中,要让每个商品(Item)在购物车(ShoppingCar)中只出现一次,如果放相同的商品到车上就只更新该商品的数量而不增加商品项。
2.2、Creator(创造者)
A是B的容器或者A和B是聚合关系 A有初始化B所需的信息 A需要记录/使用B的实例 具有以上特性,可让A具有创建/创造B类对象的责任 例如:我们使用过的工厂类ConnectionFactory/SessionFactory以及spring中的容器都是这个遵循这种责任配置模式下的产物。
2.3、Low Coupling(低耦合)
减少类间的耦合(关联/依赖等等),使一个类的修改对其它类的影响范围有所降低,从而系统变得更容易维护 使得系统变得更容易理解 总结为"不要和陌生人说话"
2.4、High Cohesion (高内聚)
提高类的通用性,并控制类的复杂程度,努力分解类使得类具有独立的责任. 优点: 高内聚可表现关联责任的一个抽象,易于实现类的重用 高内聚使维护工作变得简单 高内聚使得系统模块化工作,方便团队工作 例如: 非常低的内聚:一个类单独处理很多不同模块的事务。比如它既处理对数据库的存取,又处理用户接口图形处理。 比较低的内聚:一个类单独处理一个模块内的所有事务。 高内聚:类只处理与模块相关的功能,一个类具有一个相对独立的责任,且与其它类合作共同完成任务。
2.5、Controller (控制器)
能全面代表系统或子系统的类,比如系统事件的接收和处理通常由一个高级类来代替,称为控制器类. 不要试图只定义一个控制器类,那样会违反高内聚的原则,一个子系统会有多个控制器类,分别处理不同的事情. 控制器不是用户界面类,但通常与界面类关联(MVC模式).
2.6、Polymorphism (多态)
在OOP看来,提供了静态多态和动态多态,前者包括函数重载和模板两种形式,都是在编译期根据参数类型检查来确定调用哪个函数或使用哪个具体参数类型;
后者运行时即时编译根据内存和虚函数表查找确定调用哪个函数. 多态,尤其是动态多态性使得系统具有不变应万变的特性.
2.7、Pure Fabrication (纯虚构)
和多态性是同一概念,虚构顶层基类针对抽象编程。 纯虚构就是要虚构一个基类,将对象尽量组织成继承树的形式,客户端代码只引用了基类的形式。
例如: 设计一个绘图类,要求能在不同的系统如Linux以及Windows下绘画,如何满足?设计一个高层次的抽象类,用于分配这个职责。
2.8、Indirection (间接)
增加一个中介类,用于避免两个类直接耦合。 在实体世界向关系世界的转化中,对多对多的关系需要增加一个实体转换为两个一对多关系。
例如: n n Employee-----------Position
n 1 1 n Employee-----------Assignment-------------Position 员工类 分配类 岗位类 (这是个中介类) 一个员工对于一个分配方式 一个分配方法对于一个岗位 分配类将员工类和岗位类间的多对多关系转换为两个1对多的关系
2.9、Protected Variations (受保护变化)
估计出需求中容易变化的点,为其设计稳定的接口,也就是开闭原则:对于修改是关闭的,对于扩展是开放的。 通过扩展已有部件,可以提供新的行为以满足新需求,就使变化中的软件系统具有一定的适应性和灵活性。 已有的软件模块,最重要的抽象层模块不能再修改,就使变化中的软件系统具有一定的稳定性和延续性。 这个原则说的是,在设计一个模块的时候,应该可以使这个模块可以在不被修改的前提下被扩张。换言之,应该可以在不必修改源代码的情况下改变这个模块的行为。
三、COF设计模式概述
作用/则重点:代码的结构/完成的功能(以及这种结构的代码能解决哪一类问题) GOF模式是遵循着GRASP模式的(也就是说GOF是在GRASP模式基础之上建立的)
GOF设计模式分为23种
GoF是指Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides四个人,他们四个人被称为Gang of Four,缩写GoF。这四个人曾经合著过一本书
《Design Patterns: Elements of Reusable Object-Oriented Software》,也就是大名鼎鼎的《设计模式》一书。此书流传很广,已经是程序员界的圣经之一了。
这本书中介绍了23种设计模式,虽然设计模式其实不止这23种,但是由于这23种太常用了,所以我们一般说到设计模式,就是指GoF的23种设计模式。
四、GOF设计模式分类概述
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
4.1、创建型模式
4.1.1、工厂方法模式(Factory-Method)
1)普通工厂模式 2)多个工厂方法模式 3)静态工厂方法模式
4.1.2、抽象工厂模式(Factory)
工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则.
4.1.3、单例模式(Singleton)
1)类中定义一个private static修饰的当前类的类型的变量 2)当前类的构造器用private修饰 3)提供一个public static修饰的方法,用来获得当前类的单例对象.
4.1.4、建造者模式(Builder)
将一个复杂对象的构建与它的表示分离
4.1.5、原型模式(Prototype)
原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对象的副本
4.2、结构型模式
4.2.1、适配器模式(Adapter)
将一个类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
4.2.2、装饰器模式(Decorator)
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
4.2.3、代理模式(Proxy)
spring AOP
4.2.4、外观模式(Facade)
为系统中的一组接口提供一个一致的访问方式
4.2.5、桥接模式(桥模式(Bridge))
举例: 汽车在路上行驶,即有小汽车又有公共汽车,它们都不但能在市区中的公路上行驶,也能在高速公路上行驶。对于交通工具(汽车)有不同的类型,然而它们
所行驶的环境(路)也在变化,在软件系统中就要适应两个方面的变化?怎样实现才能应对这种变化呢?
4.2.6、组合模式(Composite)
将对象组合成树形结构以表示"部分-整体"的层次结构
4.2.7、享元模式(共享模式(Flyweigth))
String对象的运用
4.3、行为型模式
4.3.1、策略模式(Strategy)
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
4.3.2、模板方法模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
4.3.3、观察者模式(Observer)
被观察的对象的状态发生改变时,所有观察它的对象都得到通知并被自动更新
4.3.4、迭代模式(Iterator)
List Iterator
4.3.5、责任链模式(Chain of Responsibility)
Filter Interceptor
4.3.6、命令模式(Commad)
将一个请求封装为一个命令对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作
4.3.7、备忘录模式(纪念品模式(Memento))
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
4.3.8、状态模式(State)
对象中的状态改变,对象的操作也随之改变
4.3.9、访问者模式(Visitor)
它使你可以在不改变类的前提下执行作用于类中元素的新操作。
4.3.10、中介者模式(Mediator)
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
4.3.11、解释器模式
接下来将慢慢的介绍这些设计模式了!
喜欢就点个“推荐”哦!
- .NET Core 观察者模式 以及 delegate 和 event
- webapp设置适应pc和手机的页面宽高以及布局层叠图片文字
- 比较Spring AOP与AspectJ
- Promise原理解析与实现
- Spring Cloud 覆写远端的配置属性
- C语言心得一
- .NET Core装饰模式和.NET Core的Stream
- Nginx反向代理,负载均衡,redis session共享,keepalived高可用
- 多行图片hover加边框兼容IE7+
- Debian JDK安装及配置
- Python With-As
- 用 TensorFlow 创建自己的 Speech Recognizer
- Shell利剑之xargs和time
- Shell利剑之export、read和history
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- jQuery 文本属性值
- 10.4【前端开发】页面布局:如何理解 “CSS 视觉格式化模型”?
- Android Material UI控件之ShapeableImageView
- jQuery 元素操作
- jQuery 事件注册和事件处理
- 10.5 块级盒子模型(原盒子模型):两种盒子有什么不同?
- Android Material UI控件之MaterialButton
- jQuery (事件、拷贝)对象
- 10.6 border-color简写属性:如何理解四值语法?
- jQuery 插件
- dotnet 基于 dotnet format 的 GitHub Action 自动代码格式化机器人
- 10.7 border-width边框粗细:outline与border有什么不同?
- WPF 非客户区的触摸和鼠标点击响应
- Flink 解决 No ExecutorFactory found to execute the application
- 10.8 如何用js验证一下boz-sizing样式对块级盒子大小的影响?