软考高级之系统架构师之设计模式

概述

设计模式是一种通用的设计方法,实际开发中可能不止23种。为方便理解和应用,一般分为3类:

  • 创建型:通过采用抽象类所定义的接口,封装系统中对象如何创建、组合等信息。工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型:如何组合已有的类和对象以获得更大的结果。适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型:对象之间的职责及其提供服务的分配方式。责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模版方法模式、访问者模式。

根据处理范围不同,设计模式又可分为类模式和对象模式:

  • 类模式:处理类与子类的关系,通过处理这些关系来建立继承,属于静态关系,在编译时候确定下来;
  • 对象模式:处理对象之间的关系,运行时发生变化,属于动态关系。类模式可以理解为利用继承,对象之间是动态的使用组合的方式,按照设计原则来说,组合优于继承,所以可以尽可能选择对象模式。

创建型

抽象对象的实例化过程,将系统与实例的创建解耦。实例由专门的工厂来实现,从而使系统针对实例的抽象接口编程,不依赖任何接口的实现,从而让使用者不需要关注对象的创建细节

Singleton

单例模式:某个类只能生成一个实例,该类提供一个全局访问点供外部获取该实例,其拓展是有限多例模式。

在这里插入图片描述

Prototype

原型模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。如使用Object类的clone方法,快速复制对象。

FactoryMethod

工厂模式:定义一个用于创建产品的接口,由子类决定生产什么产品。由子类决定要创建的具体类是哪一个。

客户类和工厂类分开。消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。

AbstractFactory

抽象工厂模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关或相互依赖的产品(对象)。允许客户创建对象的家族,而无需指定他的具体类。

Builder

建造者模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。

结构型

结构型模式主要用于处理类和对象的组合,以获得更大的结构。这个概念可以区分大多设计模式,但是也有些比较模糊的,例如:代理模式,既完成组合,也有职责的分配,但是它依赖被归类于结构型

Proxy

代理(Proxy)模式,为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。包装对象,以控制对此对象的访问。

Adapter

适配器模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。封装对象,并提供不同的接口。

Bridge

桥接模式:将类的抽象与实现分离,使它们可以独立变化。用组合关系代替继承关系来实现的,从而降低抽象和实现这两个可变维度的耦合度。可以将接口和实现分离,提高可扩展性,对客户端隐藏实现的细节。

将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。

Decorator

装饰模式:动态地给对象增加一些职责,即增加其额外的功能。包装一个对象,以提供新的行为。

装饰器和被装饰的对象有相同的接口,装饰器在使用时获得被装饰的对象,为其增加新的操作。
在这里插入图片描述

Facade

外观模式:门面模式,为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。简化一组类的接口。

外部与一个子系统的通信必须通过一个统一的门面对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。每一个子系统只有一个门面类,而且此门面类只有一个实例,也就是说它是一个单例模式。但整个系统可以有多个门面类。

典型应用:JDBC

Flyweight

享元模式:运用共享技术来有效地支持大量细粒度对象的复用。

元模式以共享的方式高效的支持大量的细粒度对象。享元模式能做到共享的关键是区分内蕴状态和外蕴状态。内蕴状态存储在享元内部,不会随环境的改变而有所不同。外蕴状态是随环境的改变而改变的。外蕴状态不能影响内蕴状态,它们是相互独立的。将可以共享的状态和不可以共享的状态从常规类中区分开来,将不可以共享的状态从类里剔除出去。客户端不可以直接创建被共享的对象,而应当使用一个工厂对象负责创建被共享的对象。享元模式大幅度的降低内存中对象的数量。

Composite

组合模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。

行为型

行为型涉及到算法和对象间职责的分配,它还处理着对象或类之间的通信模式。在程序运行的时候总是流程复杂,需要很好的协调工作,常见行为型模式:

Template Method

模板方法模式:定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。由子类决定如何实现一个算法中的步骤。

模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。

Strategy

策略模式:定义一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户;其目的是将行为和环境分隔,当出现新的行为时,只需要实现新的策略类。。封装可以互换的行为,并使用委托来决定要使用哪一个。

Command

命令模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开;从而可用不同的请求对客户进行参数化,将请求排队或记录请求日志,支持可撤销的操作。

命令模式允许请求的一方和发送的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否执行,何时被执行以及是怎么被执行的。

类图:
在这里插入图片描述

Chain of Responsibility

职责链模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。

State

状态模式:允许一个对象在其内部状态发生改变时改变其行为能力。封装基于状态的行为,并使用委托在行为之间切换。

Observer

观察者模式:多个对象间存在一对多的依赖关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。让对象能够在状态改变时被通知。

观察者模式定义了一种一队多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

Mediator

中介者模式:也叫调停者模式,定义一个中介对象来封装简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。

中介者使得各对象不需要现实地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者对象的存在保证了对象结构上的稳定,也就说说系统的结构不会因为新对象的引入带来人量的修改工作。

调停者模式包装一系列对象相互作用的方式,使得这些对象不必相互明显作用。从而使他们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用。保证这些作用可以彼此独立的变化。调停者模式将多对多的相互作用转化为一对多的相互作用。调停者模式将对象的行为和协作抽象化,把对象在小尺度的行为上与其他对象的相互作用分开处理。

Iterator

迭代器模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。支持以不同的方式遍历一个聚合对象。

Visitor

访问者模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。

Memento

备忘录模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。

备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适时把这个对象还原到存储起来的状态。

Interpreter

解释器模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。描述如何为语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子,语言指使用规定格式和语法的代码。

解释器模式主要用在编译器中。

总结

助记脑图:
在这里插入图片描述
涉及模式之间的关系
在这里插入图片描述

实战

某公司开发出一套图形界面显示构件库。基于该库构建图形界面时,用户要求为界面定制一些特效显示,如带滚动条、艺术字体,采用装饰者模式最为灵活。

某公司欲开发一套窗体图形界面类库。该类库需要包含若干预定义的窗格(Pane)对象,例如TextPane、ListPane等,窗格之间不允许直接引用。基于该类库的应用由一个包含一组窗格的窗口组成,并需要协调窗格之间的行为。基于该类库,在不引用窗格的前提下实现窗格之间的协作,应甩开发者应采用()最为合适。

解析:
中介者模式。协作,协调等关键词。

某公司开发一个文档编辑器,该编辑器允许在文档中直接嵌入图形对象,但开销很大。用户在系统设计之初提出编辑器在打开文档时必须十分迅速,可以暂时不显示当前页面以外的图形。针对这种需求,公司可以采用()避免同时创建这些图形对象。

解析:
该编辑器需要在文档中嵌入图形对象,需要避免同时创建这些图像。代理模式可以解决直接访问对象时带来的问题,如:要访问的对象在远程机器上,或对象创建开销很大,或某些操作需要安全控制,或需要进程外的访问等。

某软件公司欲开发一个Windows平台上的公告板系统。在明确用户需求后,该公司的架构师决定采用Command模式实现该系统的界面显示部分,并设计UML类图如下图所示。图中与Command模式中的Invoker角色相对应的类是(),与ConcreteCommand角色相对应的类是()。
在这里插入图片描述
答案:MenuItem、Open。

某软件公司欲设计一款图像处理软件,帮助用户对拍摄的照片进行后期处理。在软件需求分析阶段,公司的系统分析师识别出了如下3个关键需求:

  • 图像处理软件需要记录用户在处理照片时所有动作,并能够支持用户动作的撤销与重做等行为。
  • 图像处理软件需要根据当前正在处理的照片的不同特征选择合适的处理操作,处理操作与照片特征之间具有较为复杂的逻辑关系。
  • 图像处理软件需要封装各种图像处理算法,用户能够根据需要灵活选择合适的处理算法;软件还要支持高级用户根据一定的规则添加自定义处理算法。

在系统设计阶段,公司的架构师决定采用设计模式满足上述关键需求中对系统灵活性与扩展性的要求。
为了支持灵活的撤销与重做等行为,采用()最为合适;
为了封装图像操作与照片特征之间的复杂逻辑关系,采用()最为合适;
为了实现图像处理算法的灵活选择与替换,采用()最为合适。

问题一:命令模式
问题二:状态模式
问题三:策略模式

解析:
针对需求1,为了支持灵活的撤销与重做等行为,采用命令模式最为合适,因为命令模式可以将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,还可以对请求排队,或记录请求日志,以及支持可撤销的操作。

针对需求2,为了封装图像操作与照片特征之间的复杂逻辑关系,采用状态模式最为合适,因为状态模式将每一个条件分支放入一个独立的类中,这样就可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

针对需求3,为了实现图像处理算法的灵活选择与替换,采用策略模式最为合适,因为策略模式定义一系列的算法,把它们封装起来,并且使它们可相互替换,使得算法可独立于使用它的客户而变化。

某公司欲开发一门户网站,将公司的各个分公司及办事处信息进行整合。决定采用Composite设计模式来实现公司的组织结构关系,并设计如下图所示的UML类图。图中与Composite模式中的Component角色相对应的类是(),与Composite角色相对应的类是()。
在这里插入图片描述
答案:Company、ConcreteCompany

解析:
组合(Composite)模式又称为整体-部分(Part-whole)模式,属于对象的结构模式。在组合模式中,通过组合多个对象形成树形结构以表示整体-部分的结构层次。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性。

Composite模式的结构如下图所示:
在这里插入图片描述

  • 类Component为组合中的对象声明接口,在适当的情况下,实现所有类共有接口的缺省行为,声明一个接口用于访问和管理Component的子部件;
  • 类Leaf在组合中表示叶结点对象,叶结点没有子结点;并在组合中定义图元对象的行为;
  • 类Composite定义有子部件的那些部件的行为,存储子部件,并在Component接口中实现与子部件有关的操作;
  • 类Client通过Component接口操纵组合部件的对象。

与Composite模式中的Component角色相对应的类是Company,与Composite角色相对应的类是ConcreteCompany。

某软件公司正在设计一个通用的嵌入式数据处理平台,需要支持多种数据处理芯片之间的数据传递与交换。该平台的核心功能之一要求能够屏蔽芯片之间的数据交互,使其耦合松散,并且可以独立改变芯片之间的交互过程。针对上述需求,采用()最为合适。

解析:
关键词,耦合松散。该系统需要能够支持不同芯片之间的数据交互,并能够独立改变芯片之间的数据交互过程。这种情况下,可以引入一个中介层,通过中介层屏蔽不同芯片之间的两两交互。中介者模式最符合要求。

一组对象以定义良好但是复杂的方式进行通信,产生的相互依赖关系结构混乱且难以理解。采用( )模式,用一个特定对象来封装一系列的对象交互,从而使各对象不需要显式地相互引用,使其耦合松散,而且可以独立地改变它们之间的交互。

解析:
中介者模式。

某广告公司的宣传产品有宣传册、文章、传单等多种形式,宣传产品的出版方式包括纸质方式、CD、DVD、在线发布等。现要求为该广告公司设计一个管理这些宣传产品的应用,采用()设计模式较为合适,该模式()。

解析:
不希望在不同的宣传产品与具体所采用的出版方式之间建立一个固定的绑定关系,以避免这两者之间的紧耦合关系。这种情形适合于采用桥接模式。属于结构型设计模式。结构型模式描述如何将类或对象合在一起形成更大的结构。桥接模式将抽象部分与它的实现部分分离,使它们都可以独立地变化。

在以下情况可以使用Bridge模式:

  • 不希望在抽象以及抽象的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻可以选择或切换实现部分
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充,使用Bridge模式可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充
  • 对一个抽象的实现部分的修改应该对用户不产生影响,即客户的代码不必重新编译

若系统中的某子模块需要为其他模块提供访问不同数据库系统的功能,这些数据库系统提供的访问接口有一定的差异,但访问过程却都是相同的,例如,先连接数据库,再打开数据库,最后对数据进行查询。针对上述需求,可以采用()设计模式抽象出相同的数据库访问过程,该设计模式()。

解析:
外观模式。JDBC属于外观(门面)模式的最典型应用。对象的结构模式,要求外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义一个高层接口,这个接口使得这一子系统更加容易使用。

某软件公司承接了为某工作流语言开发解释器的工作。该工作流语言由多种活动节点构成,具有类XML的语法结构。用户要求解释器工作时,对每个活动节点进行一系列的处理,包括执行活动、日志记录、调用外部应用程序等,并且要求处理过程具有可扩展能力。针对这种需求,公司采用( )最为恰当。(备选项:适配器、迭代器、访问者、观察者)

解析:
访问者模式。核心在于对某个具有固定结构的活动节点需要多种处理能力,且处理能力可扩展,也就是说要求在不改变原来类结构(活动节点)的基础上增加新功能。

参考

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
PyQt5是一个用于Python的GUI库,可以用于创建丰富的图形界面应用程序。在PyQt5中,我们可以通过美化窗体和控件来增加应用程序的吸引力和可用性。下面是一个使用PyQt5实现异形窗体的示例。 首先,我们需要导入PyQt5和其他必要的模块: ```python import sys from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.QtCore import Qt from PyQt5.QtGui import QPainter, QRegion, QColor ``` 然后,我们创建一个自定义的主窗口,并在其构造函数中设置窗口的样式为无标题栏窗口: ```python class MyWindow(QMainWindow): def __init__(self): super().__init__() # 设置窗口为无标题栏窗口 self.setWindowFlags(Qt.FramelessWindowHint) ``` 接下来,我们重写主窗口的paintEvent方法,并在该方法中使用QPainter绘制窗口的形状: ```python def paintEvent(self, event): painter = QPainter(self) painter.setCompositionMode(QPainter.CompositionMode_Clear) painter.fillRect(event.rect(), QColor(0, 0, 0, 0)) painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.setBrush(Qt.black) painter.drawRoundedRect(0, 0, self.width(), self.height(), 15, 15) ``` 在此示例中,我们使用了QPainter来绘制了一个带有圆角的黑色矩形,以实现异形窗体的效果。 最后,我们创建一个QApplication对象,并在其exec_方法中实例化我们自定义的主窗口: ```python if __name__ == "__main__": app = QApplication(sys.argv) window = MyWindow() window.show() sys.exit(app.exec_()) ``` 通过运行以上代码,我们就可以看到一个带有异形窗体的窗口实例。 使用PyQt5的美化窗体和控件功能,我们可以实现更加吸引人和独特的图形界面效果,提升应用程序的用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

johnny233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值