设计模式
透查本质
All problems in computer science can be solved by another level of indirection.
设计模式
创建型模式
对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。
工厂模式
我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
举例:通过传入不同类型来返回不同的对象,例如媒体有音频,视频,图片
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式同时解决了两个问题, 所以违反了单一职责原则:
- 将默认构造函数设为私有, 防止其他对象使用单例类的
new运算符。 - 新建一个静态构建方法作为构造函数。 该函数会 “偷偷” 调用私有构造函数来创建对象, 并将其保存在一个静态成员变量中。 此后所有对于该函数的调用都将返回这一缓存对象。
如数据库实例。
建造者模式
使用多个简单的对象一步一步构建成一个复杂的对象
我们来思考如何创建一个 房屋House对象。 建造一栋简单的房屋, 首先你需要建造四面墙和地板, 安装房门和一套窗户, 然后再建造一个屋顶。 但是如果你想要一栋更宽敞更明亮的房屋, 还要有院子和其他设施 (例如暖气、 排水和供电设备), 那又该怎么办呢?
同时可以定义主管类,对客户端隐藏创建细节。主管类里面以特定构造步骤的顺序创建产品和配置产品。
如果你需要创建的各种形式的产品, 它们的制造过程相似且仅有细节上的差异, 此时可使用生成器模式。
基本生成器接口中定义了所有可能的制造步骤, 具体生成器将实现这些步骤来制造特定形式的产品。 同时, 主管类将负责管理制造步骤的顺序。
原型模式
是用于创建重复的对象,同时又能保证性能
举例:例如我有一个很复杂的类,我现在有一个已经构建好的对象了,我可以直接clone他,然后再稍微修改一些参数久可以直接用了。
并非所有对象都能通过这种方式进行复制, 因为有些对象可能拥有私有成员变量, 它们在对象本身以外是不可见的。还有一个问题你必须知道对象所属的类才能创建复制品, 所以代码必须依赖该类。 即使你可以接受额外的依赖性, 那还有另外一个问题: 有时你只知道对象所实现的接口, 而不知道其所属的具体类, 比如可向方法的某个参数传入实现了某个接口的任何对象。
结构型模式
把类或对象结合在一起形成一个更大的结构。
适配器模式
是一种结构型设计模式, 它能使接口不兼容的对象能够相互合作。
主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
举例:
类似转接器,比如usb转sata接口,这个转接器就有这个功能,你实现了usb转成sata的驱动就可以用电脑中原有的sata驱动了
类似电源适配器,不同国家的不一样,但产品是一样的
装饰者模式
允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。
动态的将新功能附加到对象上。
装饰模式是一种用于代替继承的技术 ,无须通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
代理模式
能为程序库、 框架或其他复杂类提供一个简单的接口。(静态代理,动态代理)
两个对象直接通信中提供控制访问(为了安全原因)的作用。用代理模式并不是为了源对象和目的对象的通信复杂,而是为了控制访问或负载均衡等目的。
算是一个中介,他掌握了他这一行业的资源,比如要找女朋友,中介那有各式各样的。你只需要找他就行了,而女朋友也是通过中介和你联系。这样对于客户端和服务端就分开了。
外观模式
主要是为了隐藏系统的复杂性,能为程序库、 框架或其他复杂类提供一个简单的接口。
ffmpeg中有这个思想在里面,当我们需要生成视频文件,我传入名字和路径就可以生成。同时会帮我配置一些基本信息
桥接模式
可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。 问题的根本原因在于我们试图在两个独立的维度——形状与颜色上进行扩展。这在处理继承时是很常见的问题。 通过将继承改为组合的方式来解决这个问题。 具体来说, 就是抽取其中一个维度并使之成为独立的类层次, 这样就可以在初始类中引用这个新层次的对象, 从而使得一个类不必拥有所有的状态和行为。
桥接模式通过将继承改为组合的方式来解决这个问题。 具体来说, 就是抽取其中一个维度并使之成为独立的类层次, 这样就可以在初始类中引用这个新层次的对象, 从而使得一个类不必拥有所有的状态和行为。
将m*n个实现类转换为m+n个实现类
要求开发者一开始就针对抽象层进行设计与编程。
组合模式
你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。(树形递归思想)
- 需求中体现的是部分与整体层次的结构时,如实现树状结构,可以使用组合模式
- 希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时,就应该考虑用组合模式了
组合模式中定义的所有元素共用同一个接口。 在这一接口的帮助下, 客户端不必在意其所使用的对象的具体类。
享元模式
在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 让你能在有限的内存容量中载入更多对象。 简单来说,我们抽取出一个对象的外部状态(不能共享)和内部状态(可以共享)。然后根据外部状态的决定是否创建内部状态对象。内部状态对象是通过哈希表保存的,当外部状态相同的时候,不再重复的创建内部状态对象,从而减少要创建对象的数量。
行为型模式
类和对象如何交互,及划分责任和算法。

策略模式
定义: 策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户。
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
模板方法模式
定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。
模板方法模式是把一些重复的结构框架,步骤放到父类及抽象类中。而把以一些有差异的地方定义为抽象函数。让子类去实现。
观察者模式
观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。
观察者模式解决的是一个对象状态改变时,如何自动通知其他依赖对象的问题,同时保持对象间的低耦合和高协作性。
迭代器模式
提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
C++STL中用的很多
责任链模式
使多个对象都有机会处理同一请求,从而避免请求的发送者和接受者之间的耦合关系,每个对象都是一个处理节点,将这些对象连成一条链,并沿着这条链传递该请求。
命令模式
将请求封装为一个对象,允许用户使用不同的请求对客户端进行参数化。
解决在软件系统中请求者和执行者之间的紧耦合问题,特别是在需要对行为进行记录、撤销/重做或事务处理等场景。
备忘录模式
允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。
思考一下这些状态快照。 首先, 到底该如何生成一个快照呢? 很可能你会需要遍历对象的所有成员变量并将其数值复制保存。 但只有当对象对其内容没有严格访问权限限制的情况下, 你才能使用该方式。 不过很遗憾, 绝大部分对象会使用私有成员变量来存储重要数据, 这样别人就无法轻易查看其中的内容。
备忘录模式将创建状态快照的工作委派给实际状态的拥有者原发器对象。 这样其他对象就不再需要从 “外部” 复制编辑器状态了, 编辑器类拥有其状态的完全访问权, 因此可以自行生成快照。
状态模式
定义: 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
简单理解,一个拥有状态的context对象,在不同的状态下,其行为会发生改变。
意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
何时使用:代码中包含大量与对象状态有关的条件语句。
如何解决:将各种具体的状态类抽象出来。
访问者模式
中介者模式
能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。
中介者模式是要是为了降低两个对象之间直接通信设计上的耦合度。源对象不需要知道被调用服务方的具体类,只需要调用中介者类,由中介者完成指向具体的类。
当一些对象和其他对象紧密耦合以致难以对其进行修改时, 可使用中介者模式。该模式让你将对象间的所有关系抽取成为一个单独的类, 以使对于特定组件的修改工作独立于其他组件。
解释器模式
在软件开发中,会遇到有些问题多次重复出现,而且有一定的相似性和规律性。如果将它们归纳成一种简单的语言,那么这些问题实例将是该语言的一些句子,这样就可以用“编译原理”中的解释器模式来实现了。
如同正则表达式,他是一种”迷你语言”。
解释器模式实现的关键是定义文法规则、设计终结符类与非终结符类、画出结构图,必要时构建语法树
各个模式之间的区别
外观模式,中介者模式、代理模式的区别
外观模式:针对客户端和子系统之间,通过一个高层接口简化客户端访问子系统的复杂度
中介者模式:针对子系统内部模块之间,通过一个中介者简化各对象间的相互引用
代理模式:用一个代理类代表另一个类的功能,但是不改变被代理类的功能。目的是控制对被代理类的访问。
