基于GRASP原则的设计模式

  • 1.GRASP原则
  • 2.设计模式解决问题的方案
  • 3.实际编程中的设计模式选择
    • 3.1. 单例模式
    • 3.2 策略模式
    • 3.3 代理模式
    • 3.4 观察者模式
    • 3.5 装饰模式:
    • 3.6 适配器模式:
    • 3.7 适配器模式
    • 3.8 命令模式
    • 3.9 组合模式
    • 3.10 简单工厂模式
  • 4.如何使用设计模式

1.GRASP原则

GRASP是通用职责分配软件模式(General Responsibility Assignment Software Patterns)的缩写

主要包括9个模式,这些模式是设计OO系统的基础。这9个模式如下:

  • 创建者(Creator)
  • 信息专家(Information Expert)
  • 低耦合(Low coupling)
  • 控制器(Controller)
  • 高内聚(High Cohesion)
  • 多态性(Polymorphism)
  • 纯虚构(Pure Fabrication)
  • 间接性(Indi rection)
  • 防止变异(Protected Variations)

2.设计模式解决问题的方案

问题
存在违反SRP原理的类 AdsAccount

  • startCampaign calculateCampaignStats 方法使用通用方法getCampaignImpressions。
  • 营销团队改进了印象计算逻辑,他们希望将其应用于新的广告系列。
  • 开发人员更新并测试了 startCampaign 和 getCampaignImpressions 方法。
  • 市场营销团队批准了更改,并部署了新版本。
  • 一段时间后,出现了广告统计信息的使用了新的计算方式,分析团队使用了不一致的数据。

解决方案
解决方案非常简单。我们只需要将我们的逻辑拆分为单独的类。
现在我们有了遵守SRP原则的三个类:StatsCalculator ,CampaignLauncher,和 CampaignSaver。
每个新类都不依赖于其他类。我们有单独的私有方法来获取广告印象——每个团队有自己的逻辑。

AdsAccount 现在起着门面作用。它负责创建几个新类的实例和委托方法调用。

问题
假设,您正在创建一个送餐应用程序。您有一个移动应用程序,您的用户可以在其中创建和查看订单。
解决方案
我们可以通过多种方式来解决这个问题。我们可以扩展 OrderPresenter ,增加一个用于创建电子邮件视图的新方法。我们也可以为电子邮件创建另一个表现层模块。在这两种情况下,我们都必须更新控制器以匹配新的表现层API。

问题
假设我们需要实现一个电子钱包应用程序,在这里我们可以将钱从一张卡转移到另一张卡
解决方案
要遵循LSP,我们需要为卡添加一个父类以支持交互性。这种方法保证了我们将始终拥有 withdraw 方法。

3.实际编程中的设计模式选择

3.1. 单例模式

优点:
1.在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。这样就 防止其它对象对自己的实例化,确保所有的对象都访问一个实例
2.单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
3.提供了对唯一实例的受控访问。
4.由于在系统内存中只存在一个对象,因此可以 节约系统资源,当 需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
5.允许可变数目的实例。
6.避免对共享资源的多重占用。

适用场景:
单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。

3.2 策略模式

优点
(1)策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。

(2)使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。

3.3 代理模式

实现方式:

a) 为真实类和代理类提供的公共接口或抽象类。(租房)

b) 真实类,具体实现逻辑,实现或继承a。(房主向外租房)

c) 代理类,实现或继承a,有对b的引用,调用真实类的具体实现。(中介)

d) 客户端,调用代理类实现对真实类的调用。(租客租房)
两种模型(推模型和拉模型):

3.4 观察者模式

观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

实现方式:

a) 角色抽象类(提供对观察者的添加,删除和通知功能)。

b) 角色具体类,实现a,维护一个c的集合(对角色抽象类的实现)。

c) 观察者抽象类(被角色通知后实现的方法)。

d) 观察者实现类,实现c(多个)。

注:JDK提供了对观察者模式的支持,使用Observable类和Observer接口

■  推模型是假定主题对象知道观察者需要的数据;而拉模型是主题对象不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。

■  推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要。

3.5 装饰模式:

实现方式:

a) 抽象的被装饰角色 (所有的角色都要直接或间接的实现本角色)

b) 具体的被装饰角色,实现或继承a (被功能扩展的角色)

c) 装饰角色,实现或继承a (本类有对a的引用,所有的具体装饰角色都需要继承这个角色)

d) 多个具体修饰角色 ,继承c(对被装饰角色的功能扩展,可以任意搭配使用)

意图:

动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。该模式以对客 户端透明的方式扩展对象的功能。

适用环境:

(1)在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

(2)处理那些可以撤消的职责。

(3)当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的 子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

3.6 适配器模式:

适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
实现方式:

a) 目标抽象角色(定义客户要用的接口)

b) 适配器(实现a,维护一个c的引用,作为一个转换器被d调用)

c) 待适配器(真正需要被调用的)

d) 客户端(此类,借用a类的实例调用c类的方法,类似静态代理,但是解决的问题不同)

3.7 适配器模式

  1. 更好的复用性

系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。

  1. 更好的扩展性

在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。

3.8 命令模式

将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录日志,以及支持可撤销的操作

将“发出请求的对象”和”接收与执行这些请求的对象”分隔开来。

实现方式:

a) 抽象的命令角色 , 如:菜单(规定可以点哪些菜)

b) 具体的命令角色(实现a 维护一个对c的引用),如:订单(已点的菜)

c) 接收者(具体执行命令的角色),实际操作时,很常见使用"聪明"命令对象,也就是直接实现了请求,而不是将工作委托给c (弊端?) 如:厨师接收订单后做菜

d) 调用者(维护一个对a的引用),如:服务员负责点菜并把订单推给厨师

e) 客户端 调用d发出命令进而执行c的方法,如:顾客点餐

3.9 组合模式

将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和复杂对象的使用具有一致性。

实现方式:

a) 抽象的构件接口 (规范执行的方法),b及c都需实现此接口,如:Junit中的Test接口

b) 叶部件(实现a,最小的执行单位),如:Junit中我们所编写的测试用例

c) 组合类(实现a并维护一个a的集合[多个b的组合]),如:Junit中的 TestSuite

d) 客户端 可以随意的将b和c进行组合,进行调用

3.10 简单工厂模式

就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

实现方式:

a) 抽象产品类(也可以是接口)

b) 多个具体的产品类

c) 工厂类(包括创建a的实例的方法)

4.如何使用设计模式

设计模式不是为每个人准备的,而是基于业务来选择设计模式,需要时就能想到它。要明白一点,技术永远为业务服务,技术只是满足业务需要的一个工具。我们需要掌握每种设计模式的应用场景、特征、优缺点,以及每种设计模式的关联关系,这样就能够很好地满足日常业务的需要。

许多设计模式的功能类似,界限不是特别清楚(为了能让大家更好的理解,每个章节后面都列出了类似功能设计模式之间的对比)。大家不要疑惑,设计模式不是为了特定场景而生的,而是为了让大家可以更好和更快地开发。

设计模式只是实现了七大设计原则的具体方式,套用太多设计模式只会陷入模式套路陷阱,最后代码写的凌乱不堪。

在实际工作中很少会规定必须使用哪种设计模式,这样只会限制别人。不能为了使用设计模式而去做架构,而是有了做架构的需求后,发现它符合某一类设计模式的结构,在将两者结合。

设计模式要活学活用,不要生搬硬套。想要游刃有余地使用设计模式,需要打下牢固的程序设计语言基础、夯实自己的编程思想、积累大量的时间经验、提高开发能力。目的都是让程序低耦合,高复用,高内聚,易扩展,易维护。

1. 需求驱动

不仅仅是功能性需求,需求驱动还包括性能和运行时的需求,如软件的可维护性和可复用性等方面。设计模式是针对软件设计的,而软件设计是针对需求的,一定不要为了使用设计模式而使用设计模式,否则可能会使设计变得复杂,使软件难以调试和维护。

2. 分析成功的模式应用项目

对现有的应用实例进行分析是一个很好的学习途径,应当注意学习已有的项目,而不仅是学习设计模式如何实现,更重要的是注意在什么场合使用设计模式。

3. 充分了解所使用的开发平台

设计模式大部分都是针对面向对象的软件设计,因此在理论上适合任何面向对象的语言,但随着技术的发展和编程环境的改善,设计模式的实现方式会有很大的差别。在一些平台下,某些设计模式是自然实现的。

不仅指编程语言,平台还包括平台引入的技术。例如,Java EE 引入了反射机制和依赖注入,这些技术的使用使设计模式的实现方式产生了改变。

4. 在编程中领悟模式

软件开发是一项实践工作,最直接的方法就是编程。没有从来不下棋却熟悉定式的围棋高手,也没有不会编程就能成为架构设计师的先例。掌握设计模式是水到渠成的事情,除了理论只是和实践积累,可能会“渐悟”或者“顿悟”。

5.避免设计过度

设计模式解决的是设计不足的问题,但同时也要避免设计过度。一定要牢记简洁原则,要知道设计模式是为了使设计简单,而不是更复杂。如果引入设计模式使得设计变得复杂,只能说我们把简单问题复杂化了,问题本身不需要设计模式。

这里需要把握的是需求变化的程度,一定要区分需求的稳定部分和可变部分。一个软件必然有稳定部分,这个部分就是核心业务逻辑。如果核心业务逻辑发生变化,软件就没有存在的必要,核心业务逻辑是我们需要固化的。对于可变的部分,需要判断可能发生变化的程度来确定设计策略和设计风险。要知道,设计过度与设计不足同样对项目有害。

学习设计模式,死记硬背是没用的,还要从实践中理解,本教程后面会结合实例和源码来讲解如何使用设计模式。

需要特别声明的是,在日常应用中,设计模式从来都不是单个设计模式独立使用的。在实际应用中,通常多个设计模式混合使用,你中有我,我中有你。下图完整地描述了设计模式之间的混用关系,希望对大家有所帮助。

基于GRASP原则的设计模式相关推荐

  1. 提升代码质量的方法:领域模型、设计原则、设计模式

    点击上方"服务端思维",选择"设为星标" 回复"669"获取独家整理的精选资料集 回复"加群"加入全国服务端高端社群「后 ...

  2. wordvba编程代码大全_面向对象、设计原则、设计模式、编程规范、重构

    面向对象.设计原则.设计模式.编程规范.重构 面向对象 主流的三个编程风格有:面向对象,面向过程,函数式编程. 面向对象是最主流的风格,面向对象具有丰富的特性(封装,抽象,继承,多态). 面向对象 面 ...

  3. 运用GRASP原则来做uml交互类图-------pos机实例

    重要的几个GRASP原则:1.控制器模式   2.创建者模式 (原则)3.信息专家模式(原则) 4. 高内聚 低耦合   这里所说的模式并不是java中针对具体的事件的设计模式 主成功场景的几个操作: ...

  4. 类设计原则及设计模式(一篇就够)

    类设计原则及设计模式 类设计的六大原则 设计模式定义 设计模式的分类 创建型模式 1. 简单工厂和工厂方法模式 定义和分类 2. 抽象工厂模式 3. 单例模式 定义 优缺点 饿汉式单例与懒汉式单例类比 ...

  5. Python、设计原则和设计模式-创建类设计模式

    Python.设计原则和设计模式 前言 程序的目标:高内聚 低耦合 有哪些设计原则 设计原则是「高内聚.低耦合」的具体落地. 单一职责原则要求在软件系统开发.设计中,一个类只负责一个功能领域的相关职责 ...

  6. 面向对象分析与设计——GRASP原则

    要学习设计模式,有些基础知识是我们必须要先知道的,设计模式是关于类和对象的一种高效.灵活的使用方式,也就是说,必须先有类和对象,才能有设计模式的用武之地,否则一切都是空谈,那么类和对象是从那冒出来的呢 ...

  7. 7.5 GRASP原则五:高内聚 High Cohesion

    GRASP原则五:高内聚 High Cohesion  How to keep objects focused, understandable and manageable, and as a si ...

  8. 面向对象编程,设计原则,设计模式

    2019独角兽企业重金招聘Python工程师标准>>> 面向对象编程,设计原则,设计模式 面向对象编程 面向对象编程与面向过程编程的区别 面向对象软件开发的优点 面向对象编程语言 C ...

  9. 笔记:Head First设计原则和设计模式

    Head First 设计原则和设计模式 原则一:封装变化.找出应用中可能会变化之处,把它独立出来,不要和那些不需要变化的混在一起 原则二:针对接口编程,而不是针对实现编程 原则三:多用组合,少用继承 ...

最新文章

  1. Get/POST方法提交的长度限制
  2. 字符编码解码整合工具
  3. ML.NET Cookbook:(5)如何查看中间过程数据?
  4. matlab空间曲面拟合,matlab如何进行曲面拟合
  5. 信奥中的数学:母函数
  6. Android平板app图标,安卓手机应用图标显示为默认的机器人,平板显示正常
  7. freerdp linux下连接windows远程终端工具
  8. struts的action访问servlet的IOC方式与非IOC方式
  9. 快速入门(完整):Python练手经典实例100个 (让你的Python技能点全亮)
  10. C3P0连接池的基本配置与使用
  11. 手把手教你如何破解无线路由密码
  12. 云计算,大数据,人工智能
  13. Linux笔记------关闭系统漏洞补丁(spectre meltdown补丁)
  14. Mybatis——注入执行sql查询、更新、新增以及建表语句
  15. 【Leetcode】[190] 颠倒二进制位
  16. echarts修改标题字体大小、颜色、位置、内容
  17. Unity小游戏——3D坦克大战
  18. layui 动态绑定下拉框
  19. 时间格式化函数,TS版本
  20. 编写计算机取余程序_计算机软件amp;硬件

热门文章

  1. 用VB代码把4位数字转化为汉字数字
  2. 某APP收费音频无会员绕过下载过程分析
  3. 记忆中的高中,总是幸福的
  4. JS的ES5和ES6新增的方法(重点)
  5. UGUI上展示3d模型
  6. APP专项测试点分析
  7. 女友生日祝福短信精编:经典生日文案
  8. 中兴通讯股份有限公司
  9. 气门油封对发动机性能的重要性
  10. 视频怎么做慢动作对比分析?视频动作分析软件哪个好?