访问者模式
本博客大部分内容来于免费在线学习设计模式
1:访问者模式访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。
2:访问者模式问题假如你的团队开发了一款能够使用巨型图像中地理信息的应用程序。图像中的每个节点既能代表复杂实体(例如一座城市),也能代表更精细的对象(例如工业区和旅游景点等)。如果节点代表的真实对象之间存在公路,那么这些节点就会相互连接。在程序内部,每个节点的类型都由其所属的类来表示,每个特定的节点则是一个对象。
一段时间后,你接到了实现将图像导出到 XML 文件中的任务。这些工作最初看上去非常简单。你计划为每个节点类添加导出函数,然后递归执行图像中每个节点的导出函数。解决方案简单且优雅:使用多态机制可以让导出方法的调用代码不会和具体的节点类相耦合。
但是架构师拒绝批准对已有节点类进行修改。他认为这些代码已经是产品了,不想冒险对其进行修改,因为修改可能会引入潜在的缺陷。他还质疑在节点类中包含导出 XML 文件的代码是否有意义。这些类的主要工作是处理地理数据。导出 XML 文件的代码放在这里并不合适。还有另一个原因,那就是在此项任务完成后, 营销部门很有可能会 ...
模板方法模式
本博客大部分内容来于免费在线学习设计模式
1:模板方法模式模板方法模式是一种行为设计模式,它在超类中定义了一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤。
2:模板方法问题在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关。
例如,去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业务、对银行工作人员进行评分等,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,可以延迟到子类中实现。
这样的例子在生活中还有很多,例如,一个人每天会起床、吃饭、做事、睡觉等,其中“做事”的内容每天可能不同。我们把这些规定了流程或格式的实例定义成模板,允许使用者根据自己的需求去更新它,例如,简历模板、论文模板、Word 中模板文件等。
3:模板方法解决方案模板方法模式建议将算法分解为一系列步骤,然后将这些步骤改写为方法,最后在 “模板方法” 中依次调用这些方 ...
策略模式
本博客大部分内容来于免费在线学习设计模式
1:策略模式策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。
2:策略模式问题你设计了一款地图程序。我相信大家都用过地图app,而这些程序中提供了多种策略来进行导航。步行,公交车,地铁,骑行,自驾等多种方法。如果将这些算法全部写在一个类中,这个类的体积臃肿,对某个算法进行任何修改都会影响整个类,从而增加在已有正常运行代码中引入错误的风险。同时将花费大量时间在合并冲突上。
3:策略模式解决方案策略模式建议找出负责用许多不同方式完成特定任务的类, 然后将其中的算法抽取到一组被称为策略的独立类中。
名为上下文的原始类必须包含一个成员变量来存储对于每种策略的引用。上下文并不执行任务,而是将工作委派给已连接的策略对象。上下文不负责选择符合任务需要的算法——客户端会将所需策略传递给上下文。实际上,上下文并不十分了解策略,它会通过同样的通用接口与所有策略进行交互,而该接口只需暴露一个方法来触发所选策略中封装的算法即可。
因此,上下文可独立于具体策略。这样你就可在不修改上下文代码或其他策 ...
状态模式
本博客大部分内容来于免费在线学习设计模式
1:状态模式状态模式是一种行为设计模式,让你能在一个对象的内部状态变化时改变其行为,使其看上去就像改变了自身所属的类一样。
2:状态模式问题状态模式与有限状态机的概念紧密相关。其主要思想是程序在任意时刻仅可处于几种有限的状态中。在任何一个特定状态中,程序的行为都不相同,且可瞬间从一个状态切换到另一个状态。不过,根据当前状态,程序可能会切换到另外一种状态,也可能会保持当前状态不变。这些数量有限且预先定义的状态切换规则被称为转移。
对这种有状态的对象编程,传统的解决方案是:将这些所有可能发生的情况全都考虑到,然后使用 if-else 或 switch-case 语句来做状态判断,再进行不同情况的处理。但是显然这种做法对复杂的状态判断存在天然弊端,条件判断语句会过于臃肿,可读性差,且不具备扩展性,维护难度也大。且增加新的状态时要添加新的 if-else 语句,这违背了“开闭原则”,不利于程序的扩展。
3:状态模式解决方案状态模式建议为对象的所有可能状态新建一个类,然后将所有状态的对应行为抽取到这些类中。
原始对象被称为上下文(context),它 ...
备忘录模式
本博客大部分内容来于免费在线学习设计模式
1:备忘录模式备忘录模式是一种行为设计模式, 允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。
2:备忘录模式问题在我们的日常生活中,撤销操作已经是每个编辑程序不可或缺的一部分了。一个程序如果没有撤销的能力。对于这一程序的用户体验将造成极大影响。那么撤销功能怎么实现呢?你选择采用直接的方式来实现该功能:程序在执行任何操作前会记录所有的对象状态,并将其保存下来。当用户此后需要撤销某个操作时,程序将从历史记录中获取最近的快照,然后使用它来恢复所有对象的状态。
如何生成一个快照呢?你需要遍历对象的所有成员变量并将其数值复制保存。但只有当对象对其内容没有严格访问权限限制的情况下,你才能使用该方式。不过很遗憾,绝大部分对象会使用私有成员变量来存储重要数据,这样别人就无法轻易查看其中的内容。
现在先暂时忽略这个问题,假设所有对象的成员变量都可以任意访问。这样你可以随时生成对象快照,但是这里还有另外一个很严重的问题-未来你可能添加一些成员变量,那么你将不得不对负责复制受影响对象状态的类进行更改
还有更多问题。让我们来考虑编辑器(Editor)状 ...
中介者模式
本博客大部分内容来于免费在线学习设计模式
1:中介者模式中介者模式是一种行为设计模式,能让你减少对象之间混乱无序的依赖关系。该模式会限制对象之间的直接交互,迫使它们通过一个中介者对象进行合作。
2:中介者模式问题在现实生活中,常常会出现好多对象之间存在复杂的交互关系,这种交互关系常常是“网状结构”,它要求每个对象都必须知道它需要交互的对象。例如,每个人必须记住他(她)所有朋友的电话;而且,朋友中如果有人的电话修改了,他(她)必须让其他所有的朋友一起修改,这叫作“牵一发而动全身”,非常复杂。
3:中介者模式解决方案中介者模式建议你停止组件之间的直接交流并使其相互独立。这些组件必须调用特殊的中介者对象,通过中介者对象重定向调用行为,以间接的方式进行合作。最终,组件仅依赖于一个中介者类,无需与多个其他组件相耦合。
如果把这种“网状结构”改为“星形结构”的话,将大大降低它们之间的“耦合性”,这时只要找一个“中介者”就可以了。如前面所说的“每个人必须记住所有朋友电话”的问题,只要在网上建立一个每个朋友都可以访问的“通信录”就解决了。这样的例子还有很多,例如,你刚刚参加工作想租房,可以找“房屋 ...
单例模式
本博客大部分内容来于免费在线学习设计模式
1:单例模式单例模式是一种创建型设计模式,让你能够保证一个类只有一个实例,并提供一个访问该实例的全局节点。
2:单例模式问题单例模式同时解决了两个问题。所以违反了单一职责原则。
保证一个类只有一个实例。(eg:控制某些共享资源 (例如数据库或文件) 的访问权限。)
为该实例提供一个全局访问节点。例如存储重要对象的全局变量,它们在使用上十分方便,但同时也非常不安全,因为任何代码都有可能覆盖掉那些变量的内容,从而引发程序崩溃。
例:一个国家只有一个政府,不管身份是什么,而”某政府“就像全局访问节点一样。
3:单理模式结构
单例 (Singleton) 类声明了一个名为 getInstance获取实例的静态方法来返回其所属类的一个相同实例。
单例的构造函数必须对客户端 (Client) 代码隐藏。调用 获取实例方法必须是获取单例对象的唯一方式。
代码示例:
单例模式有多种创建方法:
这里列举三种:
通过枚举类型创建单例
12345public enum Singleton { INSTANCE; p ...
工厂方法模式
本博客大部分内容来于免费在线学习设计模式
1:工厂方法模式工厂方法模式是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。
2:工厂方法模式问题举个例子:假如你现在需要不同类型的水果:例如苹果,香蕉,梨等等。现在如果没有淘宝,水果摊这一类能提供多种水果的“工厂”。那么你买苹果需要去找苹果园,买香蕉需要去找香蕉生产地,每一个水果都需要你自行联系对应的水果生成地。很麻烦不是吗,想一想水果摊这一类的“工厂”是怎么解决这问题的?
再举一个例子:
如果你开发了一款物流管理应用。假设每一种运输方法类的构建都很复杂,需要编写大量代码。在初始版本只支持一种运输方案:卡车,于是你选择直接调用多个方法来创建卡车类。后来你需要增加另一个方式:轮船。代码部分该如何处理呢?继续直接创建一个轮船类吗。那么创建轮船类的大量代码将到处都是。更糟糕的是,如果你以后需要在程序中支持另外一种运输方式,很可能需要再次对这些代码进行大幅修改。
最后,你将不得不编写繁复的代码,根据不同的运输对象类,在应用中进行不同的处理。
3:工厂方法模式解决方案工厂方法模式建议使用特殊的工厂方法代替对于对 ...
抽象工厂模式
本博客大部分内容来于免费在线学习设计模式
1:抽象工厂模式抽象工厂(AbstractFactory)模式是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
2:抽象工厂模式问题工厂方法模式考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、计算机软件学院只培养计算机软件专业的学生等。
但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。
而抽象工厂模式将考虑多等级产品的生产。将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,
3:抽象工厂模式解决方案首先,抽象工厂模式建议为系列中的每件产品明确声明接口。然后确保所有产品变体都继承这些接口,例如(所有品牌的电视机都继承电视机接口,所有品牌的空调都继承空调接口)
然后声明抽象工厂–包含系列中所有产品构造方法的接口。例如:createWasher(创建洗衣机),createTV(创建电视机)…这些方法必须返回抽象产品类型,即我 ...
生成器模式
本博客大部分内容来于免费在线学习设计模式
1:生成器模式生成器模式是一种创建型设计模式,使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。
2:生成器模式问题在软件开发过程中有时需要创建一个复杂的对象,这个复杂对象通常由多个子部件按一定的步骤组合而成。例如,计算机是由 OPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件组装而成的,采购员不可能自己去组装计算机,而是将计算机的配置要求告诉计算机销售公司,计算机销售公司安排技术人员去组装计算机,然后再交给要买计算机的采购员。生活中这样的例子很多,如游戏中的不同角色,其性别、个性、能力、脸型、体型、服装、发型等特性都有所差异;还有汽车中的方向盘、发动机、车架、轮胎等部件也多种多样;每封电子邮件的发件人、收件人、主题、内容、附件等内容也各不相同。
解决这些问题最简单的方法是扩展基类,然后创建一系列覆盖所有参数组合的子类。但最终你将面对相当数量的子类。任何新增的参数都会让这个层次结构更加复杂。
另一种方法则无需生成子类。你可以在房屋基类中创建一个包括所有可能参数的超级构造函数,并用它来控制房屋对象 ...