在问题域部分设计的时候,也需要考虑提高性能啊。
提高性能考虑的时候呢,就是调整对象分布是吧?如果对于
频繁交换信息的两个对象,而啊它们应该是把它们放到一个
处理机上比较好啊,或者是增加保存中间结果类,这样会便于提高效率。
另外呢就是提高或降低系统的并发度
可以这个增加,或者说减少主动对象啊都可以提高性能。
并且合并一些通信频繁的类,即使它们在一个处理机上,这个
由于它们之间还需要发送这个消息,这样的话也是会造成效率损失,如果我们特别在意的话 要把它们合并。
这我们举一个例子,比如说这个例子中 流速调节器和流速探测器
是两个类,它们之间呢是个密切的一个,每隔几毫秒就要向对方发送一个消息, 但是一旦发送消息的时候会造成这个
效率损失,这时候我们把它们合并起来,这样的话就会快一些。
另外呢这个问题域部分的设计呢,还可以 有一些这个调整和这个完善属性啊,这么一些问题。
这个说我们这个定义属性类型啊,在分析模型的时候啊可能就是一个属性
的名称,在设计的时候我们要定义属性类型,定义可见性,定义这个初始值和约束啊,以及这个
对于这个复杂属性类型将它变为聚合 对象。
其他还需要考虑的问题呢还包括一些例外的处理, 如果说是我们编程语言限制了当前的这个属性类型,
我们要进行灵活的变通,以及对这个算法要进行这个优化或者构造,
这些问题呢,这个有些是我们书上介绍的一些,超出了我们这个课本上的内容啊,
是一些算法啊其他课程上的一些问题,所以这我们简单提一下,需要考虑到这 些问题,好。
最后呢我们介绍这个 采用设计模式来这个,优化我们的设计方案。
那么这就涉及到一个设计模式,设计模式实际上呢最初呢,并不是软件
工程领域的一个问题,而是建筑学在上个世纪 50
年代 建筑学大师 Alexander 在这个写的几本著作中,
提出来设计模式的一个,啊建筑学的这个模式的一些概念。
他呢这个 有一本专门的描述建筑学中的设计方案,这个设计模式一本书啊。
这里边给出了 200 多种设计模式,每一个模式呢 它描述起来呢都是一个非常统一的格式啊。
比如说也可以,它有一个注记名,非常简短的名字帮助我们这个 人呢,记忆当前这种模式的一种
什么样的这个名字,也帮助这个业内人士呢进行交流。
在就是对这个当前的这个, 这个模式它的这个上下文,或者是说背景的简单
描述啊,然后呢就是对这个模式这个解决问题的
进行描述啊,以及在就是用这个模式解决什么样的问题,以及这个
相关方案的一个规定,就是这个描述这个模式本身呢,就是一种这个
解决方案的一个片段。
这是他 给出来的模式啊,那么什么是模式呢?
实际上这个 Alexander 这个模式的这个始祖啊,
在建筑学领域,他这个给出的这个是 写了一段话,这句话呢这个不太容易理解,但是呢实际上呢是这个模式本质
这个特征,他认为模式是由三部分组成的一个规则。
一方面规则它描述的是一个环境啊一个环境, 这是一个上下文可以说。
另外呢就是说一个问题,在这个上下文有什么问题,
然后呢这个我如何解决这个问题,就是一个解决方案,并且
它是相当于一个三元组,然后这个三元组各自的一种这个关系,把这个描述清楚就是一种模式。
这个这样的话呢,这个我们从模型角度来看呢这个
上下文的话,可以理解成既是语法上下文 又是语义上下文。
语法上下文呢就说这个 在一个很大一个模型上画一个圈,然后这个圈
里边的这个模型片段,和这个外边的这些
它相邻的这些模型元素构成了一个环境啊,里边的这个如果是一个模式的话,外边就是它- 的环境。
但除此之外这个上下文啊 这个语境啊是吧?这是语法上的上下文,还有一些语义上下文就更加复杂了,
是吧?另外就是一个问题,在当前这个上下文上有什么问题?比如说它的这个
可复用性不好,或者说是这个非常麻烦,然后呢这个
效率受到一定的损失等等,这些都是一个问题。
那如何解决这个问题呢,就说将这种在当前这种环境 下将这个画在圈里面的这个模型片段,转换成另外一种
结构,然后它就可以解决这个问题,这就是 一个模式啊,所以一个模式就是一个三元组,这是非常精确的。
除此之外呢, Alexander 认为呢,这个模式可以从两个角度来 认为,首先它是一种这个
是世界上的一种元素,啊也就说不管现实世界或者软件世界,或者建筑领域的一些
领域中的一些事件, 首先模式它肯定是这个世界中的一些元素,
然后这些元素呢,它们实际上已经构成了不是一个,这个单独存在的这种原子的元素。
而是由一些原子元素组合成的一种更大力度上的
一种元素啊,这些元素呢这个都是这个描述刚才说了三者的关系。
另外呢它还是个语言的元素,就是说这个
既是现实世界的元素,然后这个元素呢也可以把它们映射到我们的模型中来,
然后呢一旦这个就变成一种指令,是吧?一旦我们这个
通过这个经验,通过自己经验把现实世界中的元素,给它挖掘成我们的一种 知识,那就形成一种指令。
那就意味着如果我们这个涉及到工程人员 都懂这些语言的话,这时候我们就是用一个很简单的一个指令,
就可以指挥着这个开发人员,这个或者说施工人员。
这个对一种特殊问题就可以指导这个施工人员,一种
非常这个简洁的一种指令来指导一种这个 比较复杂的一种解决方案的一种实施。
这叫这个语言的元素。
所以呢这个 模式呢本身是现实世界中存在的事物,
这种事物呢和我们这个模型元素,有本质的不同, 它是一个上下文有关的,并且呢
它是针对一个问题的,并且它是可以本身是一个转换是吧? 它是这个有些规则在里边可以定义的。
所以就说这个 总而言之呢,模式是存在于现实中的事物,同时也告诉我们如何创建这个事物
以及何时创造这个规则,它既是过程又是事物。
描述了有活力的事物,又描述了产生这个事物的过程。
这些文字呢应该说值得我们这个 非常深入的理解。
下面呢我们就看一下 这个建筑学领域,举一个例子啊,就 Alexander
他建筑学 的这个领域的一个模式,那就说这个 他举了一个模式,我们看看是不是他说的这个三位一体的方式啊?
首先就是背景,背景就是一个上下文有关的一个场景,啊就是在一个
长长的一尘不染的走廊是现代建筑学 场景设计或布置的一个大忌啊,也就是我们经常
在见过一些老式的一些楼,是吧?这个两边呢
全部都是房间,然后中间有一个又长又黑的一个走廊,这走廊里面什么也没有, 四周全是门,这样走上去之后我们感觉非常恐怖。
这是一个什么呢?就是一个背景或者说是一个上下文,是吧?
如果把这个设计看成是,这个模型看成是一个设计模型是吧?设计模型里边有一些
各种各样的元素组成,当一个长廊啊,然后两边全部是门,封闭的空间的时候,这时候 给人感觉非常不好,非常恐怖。
这个就提出这个问题,说在这种这个背景下,我们这个
在给定这个走廊是吧?走廊两边全部都是这个
很黑,然后呢又是没有窗户,然后全部都是封闭的门,这样子 是一个问题是吧?如何解决?然后就是把这种
与这个模型片段转换成另外一种模型片段,如何解决呢? 然后就是这种图上所示啊,首先呢在这个走廊
不要两边都给它搞成房间,最好走廊一边朝阳,另外一边是房间,
即使这段朝阳的时候,给它开上一些非常明朗的窗户,这样就是把光线透过来 之后就不会黑暗。
即使这样呢还不够,另外呢我们还可以在这个 走廊时候 ,走廊的另外一边呢给它加上一些
小型的活动空间,比如放几个沙发啊,是吧?一些这个办公室, 然后一些办公桌,一些讨论区,这样的话呢
这样就使得这个走廊呢,不会给人感觉 不是很长。
每走两步然后呢就有一个很大的空间啊,这样给人感觉非常舒服。
所以用这种转换,就可以把一个 问题给转换成解决方案,这就是模式,
这就是一个非常典型的模式,这是 Alexander 提出了三维一体 的这种方式啊。
所以呢这个,到这个上个世纪 90 年代之后,
这个很多的这个,随着面向对象的发展,很多的这个软件工程领域的一些专家呢,也看到了 这个
Alexander 在建筑领域的这个贡献,想把它移植啊平移到我们这个软件工程领域。
那么软件工程领域是不是也有模式?就产生了设计模式和分进行模式等等一些 问题啊。
所以但是它们的这些初衷啊,以及描述模式 实际如何描述模式呢,也是跟这个 Alexander 非常相似的,是借用的。
本质上没有超出 Alexander 给出那个抽象模式的概念。
比如说我们举几个例子,设计模式中的例子。
第一个观察者 这个观察者这个模式呢,实际上就是
实际上就是对于我们这个经常开发一些软件, 再就开发一些
UI 界面, 看得到啊,包括我们的一些现在正在用到的一些这个建模工具,
是吧?它这个 UI 上有不同的一种形式的一种展示。
我相同的是个 use case 图,我这边是一个图形化 use case 图,
这边可能又是一个树啊树形结构,那边呢可能这个底下呢,可能是另外一种 这个表示方式。
但是呢,所有的这些不同 展示方式啊,展示的这些这个
对象,它最后呢是到我们这个内存中,或者是我们数据上 来说是影射到相同的数据的。
你像这个图是吧? 这个数据可以用这个柱状图,也可以用一个曲线,或者是用表格的方式来表示。
但是呢,这个它们最后呢应该是统一到一个
这个都是针对着一个相同的一个内存用的数据,给它 用不同的方式展示出去。
但是一旦这个用户从一个界面更新的数据,那就要 这个把另外一些界面呢要
实时的给它更新下去,这样的话才保持我们这个 数据的一致性啊。
这实际上是一种什么呢? 也是一种这个上下文环境,只不过这种上下文环境呢,
这个可能有一些这个, 不一定是这种这个纯粹语法的
这个层面啊,可能是引用,这就使得这个问题非常复杂了。
如果是一个纯粹语法的一个上下文环境 的话,是吧?很多情况下只有
反正你可以用自动化的方式来进行构造的,比如说我们举刚才这个一个例子是吧?你根据一个
类,它这个类,你比如给你一个类图,这个类图里边呢很多类 定义对一些操作是重复的,我就如何构造一个算法,其实简单一个算法就是可以把它们
把这些这个共性的一些这个特征,给它提升到它复类上去。
这是一个什么?纯粹的语义,纯粹的语法层面上 完全可以用现在的一些模型转换技术就可以实现,但是一旦
涉及到语义上之后,这个完全用机器来 自动化的来转换模式就发现了这种困难。
除非就是有人参与进行标注啊,但是很多的目前来看, 很多的一些这个设计模式的一些自动化的研究,重构方面的研究
也开始涉及这个比较大型的这种模式, 进行模式的这种重构,当然这个目前还在研究过程之中。
针对这个来说它应该是一个语义的一个上下文啊。
就说我们要解决这个问题,这个方案就是说现在呢一般,如果我们
一般的一种这个情境下呢,
是吧?我们这个在某一个这个视图上然后更改了数据之后
我们的如果不,不给它这个传递的话,那就会导致它这个
非常这个展示不一致,可以造成很多歧义。
那如何这个 非常好的非常清晰地定义这种
一处改变多处修改的这种情况呢,是吧?那就定义了一个小的模型片段,这个模型片段中呢
这个主题就是指的内存中的那个数据, observer
呢,它有一对多,observer observer 就对应这个在 UI
中的一些不同的展示这个片段,或者说不同的展示区域。
然后呢对于一个进行修改之后呢,它会像这个 主题发送,就是像这个
当前的这个 subject 发送一个数据,然后呢让这个数据
subject 收到这个请求的时候呢,会 这个通知所有的注册到它的,所有的 observer 的进行更新啊。
我们可以用 更清晰的用这个数据图来表示啊,一个 与一个具体的这个
observer 在需要状态进行修改的时候,然后它
向这个 subject 发送一个消息 SetState。
subject 在收到这个消息的时候呢,它 调用自身 Notify 的这个操作,Notify
执行的时候呢实际上呢, 就是对所有注册到它这儿所有的 observer 啊
进行一个便利,然后调用每一个对象的 update 式的操作,然后通知 update
呢 到它这儿来取新的一个数据,并且把它展示到下面一个层面上,这样的话呢就可以实现 这个情况啊。
这个还有一种叫装饰,装饰也是一样,就说这个有些情况下呢,
我们可以动态的给一个对象添加一些额外的责任啊,这样可以生成 子类更加灵活。
特别是它能产生一种递归的这种调用。
这个一个解决方案就是什么呢?我们这个画图是吧?把图
各种编辑器,然后呢这个编辑器这个外围上有一些装饰,有些时候呢 给它装上一些这个下拉的这种这个框,
有的时候呢给它装上一些这个可以 滚动啊,有的时候这个边框不同颜色。
但是在装饰的时候呢,在这个组合这个 文本框的时候,组合下拉框的时候呢,它实际上是非常灵活啊。
如果你一个一个产生对象,是吧?那时候呢这些组合方式呢
这个会非常多,你这个编程时候呢确实会造成非常
这个复杂,这个为了解决这个问题呢,
我们用简单的这个小的这个结构,来代表所有可能的这个组合
方式,是吧?这时候呢我们可以看到,这是个装饰,
这里呢有一个组合关系,它指向了它的复类,它的复类那就意味着
这个装饰本身呢,既可以组合自身,又可以组合另外的一个功能性的一个内部的这个 TextView
啊一个文本编辑器,或者说一个图形编辑器。
然后它外围的各种装饰,是吧?这个包括拖动啊这个
下拉呀,缩放啊什么其它的一些,这个不同颜色的一些这个不同风格的一些边框啊,都可以
都是它的什么呢?都是它的一些装饰,它的 复类装饰。
既然它在这儿这个可以组合一些 像它复类有一个组合关系,那就是意味着它
既可以组合一些内部的一些,又可以组合它自身,
就是你有的人就是喜欢这个外边有一个装饰性的边框,然后装饰性的边框里边再装上一个- 什么呢?
可以拖动的这么一种这个装饰符。
这样的话呢这个就使得非常灵活啊,在装饰的时候呢
可以根据它这个,自动的给它组装
写一句话,然后给它组装成一个,根据它的这个功能模式,给它组装成不同的这种风格的这种
这个装饰和一些内容啊,这样的话呢就非常的灵活啊。
但是它这个执行起来呢,它这个通过一种机制可以保证呢 这个非常好的调用,各种各样的一些组合的这些
装饰的一些功能,是吧? 比如说在这儿一
Draw,然后呢相当于要求这个,所有的它组合的一些 不管是什么东西,组合这个 compenent
全部画这个 Draw 的方法, 然后这个 Draw 的时候呢,就是说这个它根据它这个里边儿组合了多少个
conpenent , 然后分别辨认出来然后给它画上。
然后这个 对它这个自己的这些这个子类来说呢, 它有可能组合多个子类,然后它如何
Draw 呢?首先它是这个 重写了这个 decorator
的这个复类的方法,但是呢 重写时候它先把原来的这个,它复类的方法给它
这个继承过来,然后呢再有自己的,再便于自己的 Draw。
这样的话呢就保证,这个任何的这个 Draw 方法 这个 decorator
的 Draw 方法的时候,可以根据它这个 实际组合了哪些对象,然后呢这个
根据它的对象来保证它的行为,也就是说用结构来指导行为 这样的话呢非常灵活。
还有一种就是中介者,中介者呢就是 对于一些,啊,这个
中介对象,然后这个 这个,就产生一种中介对象,然后呢,由它来这个
封装对这个对象的交互,比如说我们这儿 很简单的一个片段,是吧,在这个片段里边呢
如果说一个 UI 界面,是吧,这里边有一个很复杂的一些各种各样的一些这个 人机的这个交互的一些
components,啊,有什么文本框 editor、
还有下拉框、 还有按钮,啊,还有各种各样的一些东西,但是这些东西呢,有一些规则在里面
是吧,有时候点击一个按钮,点击一个下拉框,某些按钮得变虚
啊,这些规则呢,可以放 如果说是这个,把它们散布在各种各样的这个
事件里边,那就是会造成这个维护起来会很 有很大问题,啊,这时候呢,我们是能不能把这些
各种各样的这些构件,是吧,人机交互界面的这些构件的一些这个
约束规则给它放到一个地方,这样的话呢,就产生一个什么呢?
产生一个就是我们所说的这个中介者,是吧,中介者呢,这时候呢,
当它发生变化的时候,啊,我们这个封装在这儿,啊,这个发生变化
一旦它发生变化呢,这时候呢,我们就是把这个所有这些
上下文有关的一些规则封装在这儿,然后呢,这个 这时候呢,它这个
就是一旦我们这个发生变化,然后 再它首先调用这个 changed,啊,这个方法,啊,调用这个
changed 方法呢,就会这个 把当前的所有的一些,就比如说我这个下拉框这个发生一些变化,然后呢我会
在这里边把什么相应的一些按钮变虚,然后其他的按钮给它变实,这个 啊,这个实际,啊,这样的话呢就可以进行一个调用。
所以这里我们注意,啊,它是 changed 是调用这个 director,啊,它这个给它进行一个关联关系director中的这个
widgetchanged这个方法,啊,这里有一个,有一个这个
要点,就是说它把自身作为一个参数传进去了, 这样的话呢,这个
director呢,就根据在这个外边changed就根据它传出的这个类型来判断
啊,这个一旦这个到底是 哪一个,到底这个东西到底是个ListBox还是个
editor,然后根据这个类型找到相应的代码段,然后这个就是它一变化之后
这个变化之后会影响哪些,啊,哪些其他的一些组成部分 的状态的变化,全部给它封装到一块儿
这个widgetchanged这样的话来这个 统一的把这些变化,这些上下文规则给封装在这儿
这样就是一种中介,啊,这样的话便于维护,使得这个非常繁琐这些变化呢
不至于太松散,找的时候也非常好找,这是另外一种设计方案
好,所以这就是这个分析模式,设计模式啊这个相关的一些
这个我们这个,当然分析模式还有很多啊,我们这儿就不再详细介绍
其他的就是一些这个在问题入门分析的时候还有一个要 考虑是吧,这个进行数据验证,啊
处理系统错误、 处理例外,这个还有一些这个
一些这个设计的时候的一些 实现的有个关联性因素呢,注意就是说不要太多的
把一些实现有关的一些细节放在我们设计方案中。
本周我们就介绍完毕 好,谢谢大家!