设计模式C++-观察者模式
- 格式:doc
- 大小:64.50 KB
- 文档页数:14
27种经典设计模式
学习⽬标:
我们都知道设计模式是⼀种⾮常重要的知识,那么我们为何要学习设计模式,怎样才算是真正掌握了设计模式,学习设计模式都应该掌握哪些问题呢?下⾯我们将列举出设计模式相关的若⼲问题,如果你能够正确回答出下⾯的所有问题,那么你对于设计模式的掌握就算是过关了。
你能正确回答出下⾯所列举的所有和设计模式有关的问题吗?
1. 什么是设计模式?他是如何帮助你设计⾯向对象的软件系统的?
2. 根据设计模式的性质分类,27中经典设计模式可以分成哪三类?
3. 设计模式之间有没有关联,有什么样的关联?哪些数据模式可以组合使⽤?
4. 许多⼤型软件系统中实际上同时使⽤了很多种设计模式,如MVC,你知道MVC中都使⽤了哪些设计模式吗?
5. 如果给定你⼀些场景,你能找出适合于此应⽤场景的设计模式吗?(也即,你能不能将相应的设计模式实际运⽤到⾃⼰的项⽬中)
6.
我还不能回答出上述所有问题,我想开始学习:
如果你还不能流利的回答出上述所有问题,那么接下来你要做的就是:开始学习设计模式相关的知识,或者继续更新⾃⼰的现有知识库。
下⾯我会向你推荐若⼲好⽤的资料,希望他们可以帮助你快速掌握设计模式相关的知识:
参考资料1,
这是⼀个在线学习⽹站,⾥⾯详细列举了27中经典设计模式,针对每⼀种设计模式给出了详细解释,并且给出了应⽤实例(包括UML类图和实现代码),可以帮助读者从零开始学习某种设计模式。
另外,该教程也可以作为有经验的读者的“速查⼿册”来使
⽤。
参考资料2,。
在软件开发过程中,⼀个系统成败的关键就是在于其设计,如果系统设计的很好,那么在后续开发中就能少⾛弯路,并且在后续的系统维护中,能够简单、轻松,但如果系统设计中就出现了问题,那么这个系统的开发必然是痛苦的,编程⼈员的不停抱怨,维护⼈员的痛苦挣扎,最终导致系统的报废,没有⼈愿意再去关注它。
因此,⼈们⾮常希望能够在新的软件开发过程中使⽤那些在软件系统设计、开发过程中长期积累的很多好的、有价值的经验,来提⾼新系统的开发效率,保证新系统能够稳定、安全、易于维护。
所以,如何将这些有价值的经验记录下来,能够很好的交流、传递就显得⾮常重要。
对这些直接的、原始的经验,采⽤⾯向对象的⽅法进⾏抽象,提炼出很多的模式,这些模式很清晰的说明了它们所表达的关联、问题和解决⽅式之间的关系。
⽽这些在软件设计上积累、抽象出来的模式,我们称之为设计模式。
设计模式的概念简单地说,模式是⼀个出现在世界上的实物,同时也是⼀条规则,告诉你应该如何创建⼀个实物、应该在何时创建。
它既是过程,也是实物;既是对当前实物的描述,也是对创建实物的过程的描述。
我们需要这样⼀种语⾔:它让我们⾼效地交流、讨论那些常见的、重复出现的设计概念,并在这些概念上建⽴起我们的系统。
不要仅仅把模式当作解决⽅案,⽽要把它们当作设计的词汇,这些词汇可以根据⼀定的规则组合起来形成句⼦(也就是系统设计)。
C. Alexander描述:“每个模式是⼀个有三个部分的规则,它表达⼀定的关联、⼀个问题和⼀个解决⽅式之间的关系。
”设计模式可以使⼈们更加⽅便的复⽤成功的设计和体系结构。
将已证实的技术表述成设计模式也会使新系统的开发者更加容易理解其设计思路。
设计模式帮助你做出有利于系统间潜在联系的说明规范,设计模式甚⾄能够提⾼已有系统的⽂档管理和系统维护的有效性。
简⽽⾔之,设计模式可以帮助设计者更快更好的完成系统设计。
设计模式的分类在《设计模式》书中共给出了⼆⼗三个模式。
这⼆⼗三⼜根据其表现不同可分成了⼏类。
Objective-C设计模式-代理模式(Proxy)代理模式定义 代理模式(Proxy),为其他对象提供⼀种代理,以控制对这个对象的访问。
属于结构型模式,它为⼀个对象提供替代者或占位者,客户端通过代理对象访问⽬标对象,代理对象在客户端和⽬标对象之间起到中介的作⽤。
有以下⼏种代理:1. 远程代理(Remote proxy),为⼀个不同地址空间或⽹络上的对象提供本地代表。
好处是代理对象将⽹络的细节封装起来,客户端不必关⼼⽹络的存在。
2. 虚拟代理(Virtual proxy),根据需要创建重型或开销很⼤的对象。
如果需要创建⼀个资料消耗较⼤的对象,先创建⼀个开销较⼩的对象来占位表⽰,等真正需要时才创建实体对象。
这⾥起到了延迟对象实例化,来减缓对系统资源的消耗的作⽤。
3. 保护代理(protection proxy),通过不同的访问权限控制对原始对象的访问。
4. 智能引⽤代理(Smart reference proxy),当⼀个对象被引⽤时,提供⼀些额外的操作,⽐如将对此对象调⽤的次数记录下来等。
代理模式结构图:代理模式中的⾓⾊都实现的类似相同的接⼝,客户端向Proxy发送request消息时,Proxy持有RealSubject的引⽤,会将消息通过request接⼝转发给RealSubject对象,RealSubject会执⾏实际的操作间接满⾜了客户端的请求。
虚拟代理实现图⽚延时加载 在ios中应⽤开发中,经常需要显⽰⼤量的图像,如定义⼀个允许⽤户浏览相册的需求,视图以列表的形式呈现。
如果将相册中的图⽚全部加载⼜不可⾏,移动设备上的内存很有限,必然会影响性能。
⽽且在图像渲染到屏幕上之前,系统需要进⾏从磁盘上加载图⽚、解压缩等⼀些耗时操作,这些可能会影响视图显⽰的即时性。
通过虚拟代理实现图⽚延时加载可以很好的解决这些问题,实现的⽅式如下图所⽰。
图中ImageLoadProtocol协议表⽰代理模式中的抽象类,并定义了loadImage接⼝,ImageLoader表⽰⽬标对象,⽽ImageViewController既充当代理对象,它也是代理模式中的客户端⾓⾊,本来客户端⾓⾊应该是继承UITableView的⼦类来表⽰,但是这⾥视图不是通过继承,⽽是使⽤ios中的delegate委托模式把处理数据、加载图⽚等这些本属于UITableView的⼯作给它的委托对象ImageViewController来完成,这样ImageViewController也就相当于充当了客户端⾓⾊。
C# 设计模式之装饰者模式(Decorator Pattern)1.概述装饰者模式,英文名叫做Decorator Pattern 。
装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。
它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
2.特点(1)装饰对象和真实对象有相同的接口。
这样客户端对象就可以和真实对象相同的方式和装饰对象交互。
(2 )装饰对象包含一个真实对象的引用(reference )(3)装饰对象接受所有来自客户端的请求。
它把这些请求转发给真实的对象。
( 4 )装饰对象可以在转发这些请求以前或以后增加一些附加功能。
这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。
在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。
3.应用范围1.需要扩展一个类的功能,或给一个类添加附加职责。
2.需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
3.需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实4.当不能采用生成子类的方法进行扩充时。
一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
4.优点1.Decorator 模式与继承关系的目的都是要扩展对象的功能,但是Decorator 可以提供比继承更多的灵活性。
2.通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
(这一条更能体现)5.缺点1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
3.装饰模式是针对抽象组件 ( Component )类型编程。
但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。
当然也可以改变Component 接口,增加新的公开的行为,实现“半透明”的装饰者模式。
C语言实现《大话设计模式》中的代理模式例程分类:设计模式2012-06-12 11:07 545人阅读评论(0) 收藏举报设计模式语言cstructfunction[cpp]view plainc opyprint?1.#ifndef __PROXY_H__2.#define __PROXY_H__3.#include "rtthread.h"4.#include "finsh.h"5.//被追求者类6.typedef struct _SchoolGirl SchoolGirl;7.struct _SchoolGirl8.{9.char *Name;10.void (*SchoolGirlDelete)(SchoolGirl *pSchoolGirl);11.};12.static void SchoolGirlDelete(SchoolGirl *pSchoolGirl)13.{14. rt_free(pSchoolGirl);15.}16.SchoolGirl *SchoolGirlCreate(char *Name)17.{18. SchoolGirl *pSchoolGirl = (SchoolGirl *)rt_malloc(sizeof(SchoolGirl));19. pSchoolGirl->Name = Name;20. pSchoolGirl->SchoolGirlDelete = SchoolGirlDelete;21.return pSchoolGirl;22.}23.//追求者类24.typedef struct _Pursuit Pursuit;25.struct _Pursuit26.{27. SchoolGirl *mm;28.void (*PursuitDelete)(void *pPursuit);29.void (*GiveDolls)(Pursuit *pPursuit);30.void (*GiveFlowers)(Pursuit *pPursuit);31.void (*GiveChocolate)(Pursuit *pPursuit);32.};33.static void PursuitDelete(void *pPursuit)34.{35. rt_free(pPursuit);36.}37.static void PursuitGiveDolls(Pursuit *pPursuit)38.{39. rt_kprintf(" %s, 送你洋娃娃\n", pPursuit->mm->Name);40.}41.static void PursuitGiveFlowers(Pursuit *pPursuit)42.{43. rt_kprintf(" %s, 送你鲜花\n", pPursuit->mm->Name);44.}45.static void PursuitGiveChocolate(Pursuit *pPursuit)46.{47. rt_kprintf(" %s, 送你巧克力\n", pPursuit->mm->Name);48.}49.Pursuit *PursuitCreate(SchoolGirl *mm)50.{51. Pursuit *pPursuit = (Pursuit *)rt_malloc(sizeof(Pursuit));52. pPursuit->mm = mm;53. pPursuit->PursuitDelete = PursuitDelete;54. pPursuit->GiveDolls = PursuitGiveDolls;55. pPursuit->GiveFlowers = PursuitGiveFlowers;56. pPursuit->GiveChocolate = PursuitGiveChocolate;57.return pPursuit;58.}59.//代理者类60.typedef struct _Proxy Proxy;61.struct _Proxy62.{63. Pursuit *gg;64.void (*ProxyDelete)(void *pProxy);65.void (*GiveDolls)(Proxy *pProxy);66.void (*GiveFlowers)(Proxy *pProxy);67.void (*GiveChocolate)(Proxy *pProxy);68.};69.static void ProxyDelete(void *pProxy)70.{71. ((Proxy *)pProxy)->gg->PursuitDelete(((Proxy *)pProxy)->gg);72. rt_free(pProxy);73.}74.static void ProxyGiveDolls(Proxy *pProxy)75.{76. pProxy->gg->GiveDolls(pProxy->gg);77.}78.static void ProxyGiveFlowers(Proxy *pProxy)79.{80. pProxy->gg->GiveFlowers(pProxy->gg);81.}82.static void ProxyGiveChocolate(Proxy *pProxy)83.{84. pProxy->gg->GiveChocolate(pProxy->gg);85.}86.Proxy *ProxyCreate(SchoolGirl *mm)87.{88. Proxy *pProxy = (Proxy *)rt_malloc(sizeof(Proxy));89. pProxy->gg = PursuitCreate(mm);90. pProxy->ProxyDelete = ProxyDelete;91. pProxy->GiveDolls = ProxyGiveDolls;92. pProxy->GiveFlowers = ProxyGiveFlowers;93. pProxy->GiveChocolate = ProxyGiveChocolate;94.return pProxy;95.}96.#endif97.98.99.#include "Proxy.h"100.//客户端101.void ProxyModle(void)102.{103. SchoolGirl *jiaojiao = SchoolGirlCreate("李娇娇");104. Proxy *daili = ProxyCreate(jiaojiao);105. daili->GiveDolls(daili);106. daili->GiveFlowers(daili);107. daili->GiveChocolate(daili);108.109. jiaojiao->SchoolGirlDelete(jiaojiao);110. daili->ProxyDelete(daili);111.}112.113.FINSH_FUNCTION_EXPORT(ProxyModle, Proxy Modle);代理是真实对像的代表,它跟真实对像类属于关联关系,实现相同的接口,调用时调用代理,但真正处理时却是真实对像。
软件常见设计模式1.创建型模式单例模式单例模式(Singleton Pattern)是⼀种常⽤的软件设计模式,该模式的主要⽬的是确保某⼀个类只有⼀个实例存在。
当你希望在整个系统中,某个类只能出现⼀个实例时,单例对象就能派上⽤场。
⽐如,某个服务器程序的配置信息存放在⼀个⽂件中,客户端通过⼀个 AppConfig 的类来读取配置⽂件的信息。
如果在程序运⾏期间,有很多地⽅都需要使⽤配置⽂件的内容,也就是说,很多地⽅都需要创建 AppConfig 对象的实例,这就导致系统中存在多个 AppConfig 的实例对象,⽽这样会严重浪费内存资源,尤其是在配置⽂件内容很多的情况下。
事实上,类似 AppConfig 这样的类,我们希望在程序运⾏期间只存在⼀个实例对象1 class Singleton(object):2 def __init__(self):3 pass45 def __new__(cls, *args, **kwargs):6 if not hasattr(Singleton, "_instance"): # 反射7 Singleton._instance = object.__new__(cls)8 return Singleton._instance910 obj1 = Singleton()11 obj2 = Singleton()12 print(obj1, obj2) #<__main__.Singleton object at 0x004415F0> <__main__.Singleton object at 0x004415F0>1 class Singleton(object):2 def __init__(self):3 pass45 def __new__(cls, *args, **kwargs):6 if not hasattr(Singleton, "_instance"): # 反射7 Singleton._instance = object.__new__(cls)8 return Singleton._instance910 obj1 = Singleton()11 obj2 = Singleton()12 print(obj1, obj2) #<__main__.Singleton object at 0x004415F0> <__main__.Singleton object at 0x004415F0>⼯⼚模式⼯⼚模式是⼀个在软件开发中⽤来创建对象的设计模式。
1.2ok工厂方法模式factory method●别名:虚拟构造子(virtual constructor)模式,多态性(polymorphic Factory)工厂模式●用意:创建一个创建产品对象的工厂接口,将实际创建工作推迟到子类中●简单工厂模式与工厂方法模式区别⏹工厂方法模式是简单工厂模式的进一步抽象和推广。
由于使用了多态,工厂方法模式保持了简单工厂模式的优点,而且克服了他的缺点。
⏹工厂方法模式核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
⏹工厂方法模式退化后变得很像简单工厂模式。
●角色⏹抽象工厂角色⏹具体工厂角色⏹抽象产品角色⏹具体产品角色●优点⏹允许系统在不修改具体工厂角色的情况下引入新的产品。
●工厂方法返还的应当是抽象类型,而不是具体类型。
这有这样才能保证产品的多态性。
●举例⏹Collection接口的Iterator就是一个工厂方法。
●工厂方法模式和模板方法模式的关系⏹工厂方法模式,经常和模版方法模式一起联合使用.⏹模版方法本身也可能就是工厂方法模式1.3ok抽象工厂模式Abstract factory●用意:抽象工厂模式可以向客户端提供一个接口,使得客户端在不必指定产品的具体类型的情况下,创建多个产品族的产品对象。
●抽象工厂模式与工厂方法模式最大的区别在于:⏹工厂方法模式针对的是一个产品等级结构,抽象工厂模式则需要面对多个产品等级结构.⏹一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象。
显然,这时候抽象工厂模式比工厂方法模式更有效率。
⏹抽象工厂模式是工厂方法模式的进一步推广●涉及的角色⏹抽象工厂角色⏹具体工厂类角色⏹抽象产品角色⏹具体产品角色⏹●以下情况应当考虑使用抽象工厂模式⏹一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节。
这对于所有形态的工厂都是重要的。
⏹这个系统的产品有多于一个的产品族。
而系统只消费其中某一族的产品。
(这是抽象工厂模式的原始用意。
模板方法(Template Method)无处不在的Template Method如果你只想掌握一种设计模式,那么它就是Template Method!动机(Motivate):变化-----是软件设计的永恒主题,如何管理变化带来的复杂性?设计模式的艺术性和复杂度就在于如何分析,并发现系统中的变化和稳定点,并使用特定的设计方法来应对这种变化。
意图(Intent):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
-------《设计模式》GOF结构图(Struct):适用性:1.一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
2.各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
这是Opdyke和Johnson所描述过的“重分解以一般化”的一个很好的例子。
首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。
最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
3.控制子类扩展。
模板方法只在特定点调用“Hook”操作,这样就只允许在这些点进行扩展。
生活中的例子:代码实现:假如我们需要简单的读取Northwind数据库中的表的记录并显示出来。
对于数据库操作,我们知道不管读取的是哪张表,它一般都应该经过如下这样的几步:1.连接数据库(Connect)2.执行查询命令(Select)3.显示数据(Display)4.断开数据库连接(Disconnect)这些步骤是固定的,但是对于每一张具体的数据表所执行的查询却是不一样的。
显然这需要一个抽象角色,给出顶级行为的实现。
如下图:Template Method模式的实现方法是从上到下,我们首先给出顶级框架DataAccessObject的实现逻辑:1public abstract class DataAccessObject23 {4protected string connectionString;56protected DataSet dataSet;78protected virtual void Connect()910 {11 connectionString =1213 "Server=.;User Id=sa;Password=;Database=Northwind"; 1415 }1617protected abstract void Select();1819protected abstract void Display();202122protected virtual void Disconnect()2324 {25 connectionString = "";26 }2728// The "Template Method"2930public void Run()3132 {33 Connect();3435 Select();3637 Display();。
MVC设计模式讲解MVC(Model-View-Controller)是一种常用的软件设计架构模式,可以将应用程序的逻辑和用户界面分离,使代码更加可维护和可重用。
本文将对MVC设计模式进行详细讲解。
1.概念介绍:MVC是一种软件设计模式,通过将应用程序分为三个部分:模型(Model)、视图(View)和控制器(Controller),来实现代码的解耦和复用。
以下是对每个组件的简要介绍:- 模型(Model):负责封装应用程序的数据和业务逻辑。
模型通常是一个对象或一组对象,它们保存和操作应用程序的数据。
- 视图(View):负责向用户展示界面和接收用户输入。
视图是用户界面的可视化表示,可以是一个界面元素、一个窗口或一个网页等。
- 控制器(Controller):负责处理用户输入并更新模型和视图。
控制器接收用户输入,并在必要时更新模型和视图,以保持它们的同步。
2.工作流程:-用户与视图交互,触发一个事件。
-视图将事件传递给控制器。
-控制器根据事件类型进行相应的处理,并可能更新模型。
-模型将变化通知视图,以便更新显示。
-视图更新显示。
3.优点:-分离关注点:将业务逻辑、数据和用户界面分离,使每个组件的职责清晰明确。
-可测试性:由于模型、视图和控制器之间弱耦合,可以更容易地对它们进行单元测试。
-可维护性:通过将代码分离为三个不同的组件,可以更容易地理解和维护。
-可重用性:MVC模式使得模型和视图可以在不同的应用程序中重用。
4.实例应用:在桌面应用程序中,MVC模式常用于实现用户界面和数据逻辑的分离。
例如,一个音乐播放器可以使用MVC模式将播放器界面(视图)与播放列表(模型)和播放控制逻辑(控制器)分离。
在移动应用程序开发中,MVC模式也有广泛的应用。
例如,一个购物应用可以使用MVC模式将界面(视图)与购买商品的逻辑(模型)和购买按钮点击事件的处理(控制器)分开。
5.注意事项:- 视图和控制器的分离:在实际应用中,视图和控制器的分离可能并不是非常清晰。
目录1.C语言设计模式(开篇) (2)2.C语言和设计模式(继承、封装、多态) (3)2.1继承性 (3)2.2封装性 (4)2.3多态 (4)3.单件模式 (4)4.工厂模式 (5)5.抽象工厂模式 (6)6.访问者模式 (8)7.状态模式 (9)8.命令模式 (9)9.解释器模式 (10)10.备忘录模式 (11)11.观察者模式 (12)12.桥接模式 (12)13.建造者模式 (13)14.中介者模式 (14)15.策略模式 (15)16.适配器模式 (16)17.装饰模式 (17)18.亨元模式 (17)19.代理模式 (18)20.外观模式 (19)21.迭代器模式 (20)22.责任链模式 (21)23.模版模式 (22)24.组合模式 (24)25.原型模式 (25)1.C语言设计模式(开篇)关于软件设计方面的书很多,比如《重构》,比如《设计模式》。
至于软件开发方式,那就更多了,什么极限编程、精益方法、敏捷方法。
随着时间的推移,很多的方法又会被重新提出来。
其实,就我个人看来,不管什么方法都离不开人。
一个人写不出二叉树,你怎么让他写?敏捷吗?你写一行,我写一行。
还是迭代?写三行,删掉两行,再写三行。
项目的成功是偶然的,但是项目的失败却有很多原因,管理混乱、需求混乱、设计低劣、代码质量差、测试不到位等等。
就软件企业而言,没有比优秀的文化和出色的企业人才更重要的了。
从软件设计层面来说,一般来说主要包括三个方面:(1)软件的设计受众,是小孩子、老人、女性,还是专业人士等等;(2)软件的基本设计原则,以人为本、模块分离、层次清晰、简约至上、适用为先、抽象基本业务等等;(3)软件编写模式,比如装饰模式、责任链、单件模式等等。
从某种意义上说,设计思想构成了软件的主题。
软件原则是我们在开发中的必须遵循的准绳。
软件编写模式是开发过程中的重要经验总结。
灵活运用设计模式,一方面利于我们编写高质量的代码,另一方面也方便我们对代码进行维护。
对象状态阻碍对象行为:对象拥有不同的状态,往往会行使不同的行为...动机:在软件构建进程中,某些对象的状态若是改变和其行为也会随之而发生转变,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。
如何在运行时根据对象的状态来透明更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?用意:许诺一个对象在其内部状态改变时改变它的行为。
从而使对象看起来似乎修改了其行为。
------《设计模式》GOF结构图:适用性:1.一个对象的行为取决于它的状态,而且它必需在运行时刻依照状态改变它的行为。
2.一个操作中含有庞大的多分支的等条件语句,且这些分支依赖于该对象的状态。
这个状态通常用一个或多个枚举常量表示。
通常,有多个操作包含这一相同的条件结构。
State模式将每一个分支放入一个独立的类中。
这使得你可根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
代码实现:class MainAppstatic void Main(){;}public override void Deposit(double amount) {balance += amount;StateChangeCheck();}public override void Withdraw(double amount) {balance -= amount;StateChangeCheck();}public override void PayInterest(){balance += interest * balance;StateChangeCheck();}private void StateChangeCheck(){if(balance <{= new RedState(this);}else if(balance < lowerLimit){= new SilverState(this);}}}不同的状态引入不同的对象使得状态转换变得加倍明确,而且能够保证可不能显现状态不一致的情形,因为转换是原子性的----即要么完全转换过来,要么不转换。
【设计模式】外观模式代理模式中介者模式的区别外观模式个⼈理解:⼦类继承外观类的所有属性⽅法,客户端只需要跟外观类进⾏交流,实现了对所有⼦类的封装。
没有使⽤外观类如图:应⽤外观类如图:代理模式个⼈理解:代理模式是将原类进⾏封装,客户端只需要与代理进⾏交流。
代理就是原类的⼀个替⾝。
简⽽⾔之就是⽤⼀个对象代表另外⼀个对象。
强调的是个体。
中介者模式定义⼀个中介对象来封装系列对象之间的交互。
中介者使各个对象不需要显⽰地相互引⽤,从⽽使其耦合性松散,⽽且可以独⽴地改变他们之间的交互使⽤中介者模式的场合1.⼀组定义良好的对象,现在要进⾏复杂的通信。
2.定制⼀个分布在多个类中的⾏为,⽽⼜不想⽣成太多的⼦类。
可以看出,中介对象主要是⽤来封装⾏为的,⾏为的参与者就是那些对象,但是通过中介者,这些对象不⽤相互知道。
使⽤中介者模式的优点:1.降低了系统对象之间的耦合性,使得对象易于独⽴的被复⽤。
2.提⾼系统的灵活性,使得系统易于扩展和维护。
使⽤中介者模式的缺点:中介者模式的缺点是的,因为这个“中介“承担了较多的责任,所以⼀旦这个中介对象出现了问题,那么整个系统就会受到重⼤的影响。
三者的区别与联系1,中介者模式:A,B之间的对话通过C来传达。
A,B可以互相不认识(减少了A和B对象间的耦合)2,代理模式:A要送B礼物,A,B互相不认识,那么A可以找C来帮它实现送礼物的愿望(封装了A对象)3,外观模式:A和B都要实现送花,送巧克⼒的⽅法,那么我可以通过⼀个抽象类C实现送花送巧克⼒的⽅法(A和B都继承C)。
(封装了A,B⼦类)代理模式和外观者模式这两种模式主要不同就是代理模式针对的是单个对象,⽽外观模式针对的是所有⼦类。
C#设计模式系列:建造者模式(Builder)11.1 定义 建造者模式(Builder)将复杂的构建与其表⽰相分离,使得同样的构建过程可以创建不同的表⽰。
1.2 使⽤频率 中低22.1 结构图2.2 参与者 建造者模式参与者: ◊ Builder:为创建⼀个Product对象的各个部件指定抽象接⼝; ◊ ConcreteBuilder ° 实现Builder的接⼝以构造和装配该产品的各个部件 ° 定义并明确它所创建的表⽰ ° 提供⼀个检索Product的接⼝ ◊ Director:构造⼀个使⽤Builder接⼝的对象; ◊ Product ° 表⽰被构造的复杂对象。
ConcreteBuilder创建该产品的内部表⽰并定义它的装配过程 ° 包含定义组成部件的类,包括将这些部件装配成最终产品的接⼝ 在建造者模式中,Director规定了创建⼀个对象所需要的步骤和次序,Builder则提供了⼀些列完成这些步骤的⽅法,ConcreteBuilder给出了这些⽅法的具体实现,是对象的直接创建者。
3 建造者模式结构实现 Product.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Structural{public class Product{private List<string> _parts = new List<string>();public void Add(string part){_parts.Add(part);}public void Show(){Console.WriteLine("Product Parts");foreach (string part in _parts){Console.WriteLine(part);}}}} Builder.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Structural {public abstract class Builder{public abstract void BuildPartA();public abstract void BuildPartB();public abstract Product GetResult();}} ConcreteBuilder1.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Structural {public class ConcreteBuilder1 : Builder{private Product _product = new Product();public override void BuildPartA(){_product.Add("PartA");}public override void BuildPartB(){_product.Add("PartB");}public override Product GetResult(){return _product;}}} ConcreteBuilder2.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Structural {public class ConcreteBuilder2 : Builder{private Product _product = new Product();public override void BuildPartA(){_product.Add("PartX");}public override void BuildPartB(){_product.Add("PartY");}public override Product GetResult(){return _product;}}} Director.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Structural {public class Director{///<summary>/// Builder uses a complex series of steps///</summary>public void Construct(Builder builder){builder.BuildPartA();builder.BuildPartB();}}} Program.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;using DesignPatterns.BuilderPattern.Structural; namespace DesignPatterns.BuilderPattern{class Program{static void Main(string[] args){// Create director and buildersDirector director = new Director();Builder b1 = new ConcreteBuilder1();Builder b2 = new ConcreteBuilder2();// Construct two productsdirector.Construct(b1);Product p1 = b1.GetResult();p1.Show();director.Construct(b2);Product p2 = b2.GetResult();p2.Show();}}} 运⾏输出:Product PartsPartAPartBProduct PartsPartXPartY请按任意键继续. . .4、建造者模式实践应⽤ Vehicle.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Practical{///<summary>/// The 'Product' class///</summary>public class Vehicle{private string _vehicleType;private Dictionary<string, string> _parts = new Dictionary<string, string>();///<summary>/// Constructor///</summary>public Vehicle(string vehicleType){this._vehicleType = vehicleType;}///<summary>/// Indexer///</summary>public string this[string key]{get { return _parts[key]; }set { _parts[key] = value; }}public void Show(){Console.WriteLine("\n---------------------------");Console.WriteLine("Vehicle Type: {0}", _vehicleType);Console.WriteLine(" Frame : {0}", _parts["frame"]);Console.WriteLine(" Engine : {0}", _parts["engine"]);Console.WriteLine(" #Wheels: {0}", _parts["wheels"]);Console.WriteLine(" #Doors : {0}", _parts["doors"]);}}} VehicleBuilder.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Practical{///<summary>/// The 'Builder' abstract class///</summary>public abstract class VehicleBuilder{protected Vehicle vehicle;// Gets vehicle instancepublic Vehicle Vehicle{get { return vehicle; }}// Abstract build methodspublic abstract void BuildFrame();public abstract void BuildEngine();public abstract void BuildWheels();public abstract void BuildDoors();}} MotorCycleBuilder.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Practical{public class MotorCycleBuilder : VehicleBuilder {public MotorCycleBuilder(){vehicle = new Vehicle("MotorCycle");}public override void BuildFrame(){vehicle["frame"] = "MotorCycle Frame";}public override void BuildEngine(){vehicle["engine"] = "500 cc";}public override void BuildWheels(){vehicle["wheels"] = "2";}public override void BuildDoors(){vehicle["doors"] = "0";}}} CarBuilder.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Practical {public class CarBuilder : VehicleBuilder{public CarBuilder(){vehicle = new Vehicle("Car");}public override void BuildFrame(){vehicle["frame"] = "Car Frame";}public override void BuildEngine(){vehicle["engine"] = "2500 cc";}public override void BuildWheels(){vehicle["wheels"] = "4";}public override void BuildDoors(){vehicle["doors"] = "4";}}} ScooterBuilder.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Practical {public class ScooterBuilder : VehicleBuilder{public ScooterBuilder(){vehicle = new Vehicle("Scooter");}public override void BuildFrame(){vehicle["frame"] = "Scooter Frame";}public override void BuildEngine(){vehicle["engine"] = "50 cc";}public override void BuildWheels(){vehicle["wheels"] = "2";}public override void BuildDoors(){vehicle["doors"] = "0";}}} Shop.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.BuilderPattern.Practical{public class Shop{public void Construct(VehicleBuilder vehicleBuilder) {vehicleBuilder.BuildFrame();vehicleBuilder.BuildEngine();vehicleBuilder.BuildWheels();vehicleBuilder.BuildDoors();}}} Program.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;using DesignPatterns.BuilderPattern.Practical; namespace DesignPatterns.BuilderPattern{class Program{static void Main(string[] args){VehicleBuilder builder;// Create shop with vehicle buildersShop shop = new Shop();// Construct and display vehiclesbuilder = new ScooterBuilder();shop.Construct(builder);builder.Vehicle.Show();builder = new CarBuilder();shop.Construct(builder);builder.Vehicle.Show();builder = new MotorCycleBuilder();shop.Construct(builder);builder.Vehicle.Show();}}} 运⾏输出:---------------------------Vehicle Type: ScooterFrame : Scooter FrameEngine : 50 cc#Wheels: 2#Doors : 0---------------------------Vehicle Type: CarFrame : Car FrameEngine : 2500 cc#Wheels: 4#Doors : 4---------------------------Vehicle Type: MotorCycleFrame : MotorCycle FrameEngine : 500 cc#Wheels: 2#Doors : 0请按任意键继续. . .5 建造者模式适⽤情形: ◊ 需要⽣成的产品对象有复杂的内部结构 ◊ 需要⽣成的产品对象的属性相互依赖,建造者模式可以强迫⽣成顺序 ◊ 在对象创建过程中会使⽤到系统中的⼀些其他对象,这些对象在产品对象的创建过程中不易得到 建造者模式特点: ◊ 建造者模式的使⽤使得产品的内部表对象可以独⽴地变化。
【设计模式】第⼀篇:概述、耦合、UML、七⼤原则,详细分析总结(基于Java)迷茫了⼀周,⼀段时间重复的 CRUD ,着实让我有点烦闷,最近打算将这些技术栈系列的⽂章先暂时搁置⼀下,开启⼀个新的篇章《设计模式》,毕竟前⾯写了不少 “武功招式” 的⽂章,也该提升⼀下内功了⼀设计模式概述(⼀) 什么是设计模式设计模式,即Design Patterns,是指在软件设计中,被反复使⽤的⼀种代码设计经验。
使⽤设计模式的⽬的是为了可重⽤代码,提⾼代码的可扩展性和可维护性1995年,GoF(Gang of Four,四⼈组/四⼈帮)合作出版了《设计模式:可复⽤⾯向对象软件的基础》⼀书,收录了23种设计模式,从此树⽴了软件设计模式领域的⾥程碑,【GoF设计模式】(⼆) 为什么学习设计模式前⾯我们学习了 N 种不同的技术,但是归根结底,也只是 CRUD 与调⽤之间的堆砌,或许这个创意亦或是业务很完善、很强⼤,其中也巧妙运⽤了各种⾼效的算法,但是说⽩了,这也只是为了实现或者说解决某个问题⽽做的还有时候,两个⼈同时开发⼀款相同的产品,均满⾜了预期的需求,但是 A 的程序,不仅代码健壮性强,同时后期维护扩展更是便捷(这种感觉,我们会在后⾯具体的设计模式中愈发的感觉到)⽽ B 的代码却是⼀⾔难尽啊有⼀句话总结的⾮常好:设计模式的本质是⾯向对象设计原则的实际运⽤,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解也就是说,毕竟像例如Java这样⾯向对象的语⾔中,如何实现⼀个可维护,可维护的代码,那必然就是要降低代码耦合度,适当复⽤代码,⽽要实现这⼀切,就需要充分的利⽤ OOP 编程的特性和思想注:下⾯第⼆⼤点补充【耦合】的相关概念,若不需要跳转第三四⼤点【UML类图及类图间的关系】/【设计模式七⼤原则】在之前我写 Spring依赖注⼊的时候【万字长⽂】 Spring框架层层递进轻松⼊门(0C和D),就是从传统开发,讲到了如何通过⼯⼚模式,以及多例到单例的改进,来⼀步步实现解耦,有兴趣的朋友可以看⼀下哈⼆什么是耦合?(⾼/低)作为⼀篇新⼿都能看懂的⽂章,开始就⼀堆 IOC AOP等专业名词扔出去,好像是不太礼貌,我得把需要铺垫的知识给⼤家尽量说⼀说,如果对这块⽐较明⽩的⼤佬,直接略过就OK了耦合,就是模块间关联的程度,每个模块之间的联系越多,也就是其耦合性越强,那么独⽴性也就越差了,所以我们在软件设计中,应该尽量做到低耦合,⾼内聚⽣活中的例⼦:家⾥有⼀条串灯,上⾯有很多灯泡,如果灯坏了,你需要将整个灯带都换掉,这就是⾼耦合的表现,因为灯和灯带之间是紧密相连,不可分割的,但是如果灯泡可以随意拆卸,并不影响整个灯带,那么这就叫做低耦合代码中的例⼦:来看⼀个多态的调⽤,前提是 B 继承 A,引⽤了很多次A a = new B();a.method();如果你想要把B变成C,就需要修改所有new B()的地⽅为new C()这也就是⾼耦合如果如果使⽤我们今天要说的 spring框架就可以⼤⼤的降低耦合A a = BeanFactory().getBean(B名称);a.method();这个时候,我们只需要将B名称改为C,同时将配置⽂件中的B改为C就可以了常见的耦合有这些分类:(⼀) 内容耦合当⼀个模块直接修改或操作另⼀个模块的数据,或者直接转⼊另⼀个模块时,就发⽣了内容耦合。
谈到用语言,更多是语言惯用法,而非设计模式,他们是不同层面的概念,MVC 那就扯得更远了,设计模式是针对应用top down下来,而非一种特定的语言,如果为语言而模式,为模式而模式那就是缘木求鱼。
狭义的设计模式是针对面向对象这类语言,C 用的啰嗦一点,模拟出对象关系,使用GOF总结的设计模式是没问题的,但关系如果整地过于复杂就违背C语言精干的特点,就不要用C了。
广义的是针对一种编程范式中的模式,象C这种命令式语言,模拟函数式编程还是力有未逮,函数式里的模式就用不来。
C的惯用法主要集中在macro, 用好了会感觉代码清晰,重复很少。
C不是OO语言,但编程中可以应用一些OO思想。
比如对象的概念,C++的class就是struct的升级版,所以在C中一个struct 变量可以视为一个对象实例。
比如有一个玩家对象结构体struct Player,内有属性HP。
继承玩家的,有战士和法师。
那么可以这么写:struct Player {int HP;//血量};struct Warrior {struct Player base;int Attack;//攻击力int Defensive;//防御力};struct Mage {struct Player base;int MP;//魔法值int Range;//施法范围};//玩家挂了吗?int Player_IsDead(struct Player* player) {return (player->HP==0) ? 1 : 0;}//吃血void Player_DrinkRedBottle(struct Player* player, int bottle_level) { if( bottle_level == 1 ) player->HP += 100;//小瓶else if( bottle_level == 2 ) player->HP += 500;//大瓶}struct Warrior w;struct Mage m;//战士没挂就吃个小血瓶if( !Player_IsDead((struct Player*)&w) ) {Player_DrinkRedBottle((struct Player*)&w, 1);}//if( !Player_IsDead((struct Player*)&m) ) {Player_DrinkRedBottle((struct Player*)&m, 1);}这种写法不如C++的方便,缺乏足够的语法检查,但也算够用了。
观察者模式,又叫做发布-订阅(Publish/Subscribe)模式观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态发生变化时,会通知所有观察者对象,使得它们能够自动更新自己。
观察者模式的动机将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。
我们不希望为了维护一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不方便。
而观察者模式的关键对象是主题Subject和观察者Observer,一个Subject可以有任意数目的依赖它的Observer,一旦Subject的状态发生了改变,所有的Observer都可以得到通知。
Subject发出通知时并不需要知道谁是它的观察者,也就是说,具体观察者是谁,它根本不需要知道。
而任何一个具体观察者不知道也不需要知道其他观察者的存在。
什么时候应该使用观察者模式当一个对象的改变需要同时改变其他对象的时候。
而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式。
也可以理解为,当一个抽象模型有两个方面,其中一方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
总的来说,观察者模式所做的工作其实就是在解除耦合。
让耦合的双方都依赖于抽象,而不是依赖于具体。
从而使得各自的变化都不会影响另一边的变化。
工程结构(1)抽象通知者Subject.h(2)抽象观察者Observer.h(3)具体通知者ConcreteSubject.h(4)具体观察者ConcreteObserver.h(5)客户端类ObserverApp.cpp(1)抽象通知者Subject.hview plaincopy to clipboardprint?/************************************************************************* description: 主题或者抽象通知者类,一般用一个抽象类或者一个接口实现。
它把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。
抽象主题提供一个接口,可以增加或者删除观察者对象。
* remark:************************************************************************/#ifndef _SUBJECT_H_#define _SUBJECT_H_#include "Observer.h"#include <list>#include <string>#include <iostream>using namespace std;class CSubject{public:// 增加观察者virtual void Attach(CObserver* pObserver) = 0;// 移除观察者virtual void Detach(CObserver* pObserver) = 0;virtual void Notify(void) = 0;};#endif _SUBJECT_H_/************************************************************************ * description: 主题或者抽象通知者类,一般用一个抽象类或者一个接口实现。
它把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。
抽象主题提供一个接口,可以增加或者删除观察者对象。
* remark:************************************************************************/ #ifndef _SUBJECT_H_#define _SUBJECT_H_#include "Observer.h"#include <list>#include <string>#include <iostream>using namespace std;class CSubject{public:// 增加观察者virtual void Attach(CObserver* pObserver) = 0;// 移除观察者virtual void Detach(CObserver* pObserver) = 0;// 通知virtual void Notify(void) = 0;};#endif _SUBJECT_H_(2)抽象观察者Observer.hview plaincopy to clipboardprint?/************************************************************************ * description: 抽象观察者类,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己* remark:************************************************************************/ #ifndef _OBSERVER_H_#define _OBSERVER_H_class CObserver{virtual void Update() = 0;};#endif _OBSERVER_H_/************************************************************************ * description: 抽象观察者类,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己* remark:************************************************************************/ #ifndef _OBSERVER_H_#define _OBSERVER_H_class CObserver{public:virtual void Update() = 0;};#endif _OBSERVER_H_(3)具体通知者ConcreteSubject.hview plaincopy to clipboardprint?/************************************************************************ * description: 具体主题类或者具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
* remark:************************************************************************/ #ifndef _CONCRETE_SUBJECT_H_#define _CONCRETE_SUBJECT_H_#include "Subject.h"class CConcreteSubject : public CSubject{public:// 增加观察者void Attach(CObserver* pObserver){m_listObservers.push_back(pObserver);}// 移除观察者void Detach(CObserver* pObserver){m_listObservers.remove(pObserver);}// 通知void Notify(void){list<CObserver*>::iterator lIter;for (lIter = m_listObservers.begin(); lIter != m_listObservers.end(); lIter++){(*lIter)->Update();}}void SetState(const string& strState){m_strSubjectState = strState;}string GetState(void){return m_strSubjectState;}private:string m_strSubjectState;list<CObserver*> m_listObservers;};#endif _CONCRETE_SUBJECT_H_/************************************************************************ * description: 具体主题类或者具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
* remark:************************************************************************/ #ifndef _CONCRETE_SUBJECT_H_#define _CONCRETE_SUBJECT_H_#include "Subject.h"class CConcreteSubject : public CSubject{public:// 增加观察者void Attach(CObserver* pObserver){m_listObservers.push_back(pObserver);}// 移除观察者void Detach(CObserver* pObserver){m_listObservers.remove(pObserver);}// 通知void Notify(void){list<CObserver*>::iterator lIter;for (lIter = m_listObservers.begin(); lIter != m_listObservers.end(); lIter++){(*lIter)->Update();}}void SetState(const string& strState){m_strSubjectState = strState;}string GetState(void){return m_strSubjectState;}private:string m_strSubjectState;list<CObserver*> m_listObservers;};#endif _CONCRETE_SUBJECT_H_(4)具体观察者ConcreteObserver.hview plaincopy to clipboardprint?/************************************************************************ * description: 具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。