设计模式解决问题及如何选择设计模式解决问题

本文介绍了GRASP原则,包括信息专家、创建者、高内聚、低耦合等9个核心原则,以及它们在面向对象设计中的作用。设计模式作为解决问题的通用方案,如工厂模式、MVC架构、多态模式等,提供了灵活应对变化的手段。文章强调了设计应支持变化、接口编程的重要性,并探讨了如何在实际编程中选择和使用设计模式,以实现可复用和适应变化的软件系统。
摘要由CSDN通过智能技术生成

一、GRASP是什么以及包含的九个原则
GRASP,通用职责分配软件模式,它由Craig Larman提出。与其将它们称之为设计模式,不如称之为设计原则,因为它是站在面向对象设计的角度,告诉我们怎样设计问题空间中的类与分配它们的行为职责,以及明确了类之间的相互关系等,而不像GoF模式一样是针对特定问题而提出的解决方案。因此GRASP站在一个更高的角度来看待面向对象软件的设计,它是GoF设计模式的基础。GRASP是对象职责分配的基本原则,其核心思想是职责分配,用职责设计对象。它包含如下9个基本特征或原则:
1)信息专家模式对应于面向对象设计原则中的单一职责原则。
2)创建者模式与各种工厂模式(简单工厂模式、工厂方法模式和抽象工厂模式)相对应。
3)高内聚:内聚是评价一个元素的职责被关联和关注强弱的尺度。
4)低耦合:耦合是评价一个系统中各个元素之间连接或依赖强弱关系的尺度
5)控制器:控制器模式与MVC模式相对应,MVC是一种比设计模式更加高级的架构模式。
6)多态模式:在多个GoF设计模式中都有所体现,如适配器模式、命令模式、组合模式、观察者模式、策略模式等等。
7)纯虚构模式用于解决高内聚和低耦合之间的矛盾,它要求将一部分类的职责转移到纯虚构类中,在理想情况下,分配给这种虚构类的职责是为了达到高内聚和低耦合的目的。在系统中引入抽象类或接口来提高系统的扩展性也可以认为是纯虚构模式的一种应用。在很多设计模式中都体现了纯虚构模式,例如适配器模式、策略模式等等。
8)中介模式:在外观模式、代理模式、中介者模式等设计模式中都体现了中介模式。
9)受保护变化:大多数设计原则和GoF模式都是受保护变化模式的体现。


二、设计模式怎样解决设计问题?
设计模式采用多种方法解决面向对象设计者经常碰到的问题。这里给出几个问题以及使用设计模式解决它们的方法。
1.寻找合适的对象
面向对象程序由对象组成,对象包括数据和对数据进行操作的过程,过程通常称为方法或操作。对象在收到客户的请求(或消息)后,执行相应的操作。
客户请求是使对象执行操作的唯一方法,操作又是对象改变内部数据的唯一方法。由于这些限制,对象的内部状态是被封装的,它不能被直接访问,它的表示对于对象外部是不可见的。
面向对象设计最困难的部分是将系统分解成对象集合。因为要考虑许多因素:封装、粒度、依赖关系、灵活性、性能、演化、复用等等,它们都影响着系统的分解,并且这些因素通常还是互相冲突的。面向对象设计方法学支持许多设计方法。你可以写出一个问题描述,挑出名词和动词,进而创建相应的类和操作;或者,你可以关注于系统的协作和职责关系;或者,你可以对现实世界建模,再将分析时发现的对象转化至设计中。至于哪一种方法最好,并无定论。
2.指定对象接口
对象声明的每一个操作指定操作名、作为参数的对象和返回值,这就是所谓的操作的型构(signature)。对象操作所定义的所有操作型构的集合被称为该对象的接口(interface)。对象接口描述了该对象所能接受的全部请求的集合,任何匹配对象接口中型构的请求都可以发送给该对象。
在面向对象系统中,接口是基本的组成部分。对象只有通过它们的接口才能与外部交流,如果不通过对象的接口就无法知道对象的任何事情,也无法请求对象做任何事情。对象接口与其功能实现是分离的,不同对象可以对请求做不同的实现,也就是说,两个有相同接口的对象可以有完全不同的实现。
3.描述对象的实现
作在类名下面,以常规字体表示。类所定义的任何数据都在操作的下面。类名与操作之间以及操作与数据之间用横线分割。
返回类型和实例变量类型是可选的,因为我们并未假设一定要用具有静态类型的实现语言。对象通过实例化类来创建,此对象被称为该类的实例。当实例化类时,要给对象的内部数据(由实例变量组成)分配存储空间,并将操作与这些数据联系起来。对象的许多类似实例是由实例化同一个类来创建的。
下图中的虚箭头线表示一个类实例化另一个类的对象,箭头指向被实例化的对象的类

新的类可以由已存在的类通过类继承(classinheritance)来定义。当子类(subclass)继承父类(parentclass)时,子类包含了父类定义的所有数据和操作。子类的实例对象包含所有子类和父类定义的数据,且它们能完成子类和父类定义的所有操作。我们以竖线和三角表示子类关系,如下图所示。

抽象类(abstractclass)的主要目的是为它的子类定义公共接口。一个抽象类将把它的部分或全部操作的实现延迟到子类中,因此,一个抽象类不能被实例化。在抽象类中定义却没有实现的操作被称为抽象操作(abstractoperation)。非抽象类称为具体类(concreteclass)。
子类能够改进和重新定义它们父类的操作。更具体地说,类能够重定义(override)父类定义的操作,重定义使得子类能接管父类对请求的处理操作。类继承允许你只需简单的扩展其他类就可以定义新类,从而可以很容易地定义具有相近功能的对象族。
抽象类的类名以斜体表示,以与具体类相区别。抽象操作也用斜体表示。图中可以包括实现操作的伪代码,如果这样,则代码将出现在带有摺角的框中,并用虚线将该摺角框与代码所实现的操作相连,图示如下。

混入类(mixinclass)是给其他类提供可选择的接口或功能的类。它与抽象类一样不能实例化。混入类要求多继承,图示如下。

4.针对接口编程,而不是针对实现编程
对接口编程,而不是对实现编程
Programming to an Interface,not an Implementation

继承所拥有的定义 具有相同接口的对象族的能力是很重要的(通常可以从抽象类来继承)
因为 多态依赖于这种能力

当继承被恰当使用时,所有从抽象类导出的类将共享该抽象类的接口。 这意味着子类仅仅添加或重定义操作,而没有隐藏父类的操作
这时,所有的子类都能响应抽象类接口中的请求,从而 子类的类型都是抽象类的子类型

只根据抽象类中定义的接口来操纵对象有以下两个好处:
1)客户无须知道他们使用对象的特定类型,只须对象有客户所期望的接口
2)客户无须知道他们使用的对象是用什么类来实现的,他们只需知道定义接口的抽象类
这将极大地减少子系统实现之间的相互依赖关系

通过抽象对象的创建过程, 创建型模式提供不同方式以在实例化时建立接口和实现的透明连接
创建型模式确保你的系统是采用针对接口的方式书写的,而不是针对实现而书写的
5.运用复用机制
理解对象、接口、类和继承之类的概念对大多数人来说并不难,问题的关键在于如何运用它们写出灵活的、可复用的软件。设计模式将告诉你怎样去做。
6.设计应支持变化
获得最大限度复用的关键在于对新需求和已有需求发生变化时的预见性,要求你的系统设计要能够相应地改进。
为了设计适应这种变化、且具有健壮性的系统,你必须考虑系统在它的生命周期内会发生怎样的变化。

三、在实际编程中怎样选择设计模式?以及如何使用设计模式?

首先必须要了解常用的23种设计模式。

在编程中选择设计模式时,需要考虑以下几点:

考虑设计模式是怎样解决设计问题的。
通读每个模式的意图,找出和你的问题相关的一个或多个模式。
考虑你的设计中哪些是可变的 。
检查重新设计的原因 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值