设计模式 - 设计模式概述
# 掌握设计模式的层次
- 第 1 层:刚开始学编程不久,听说过什么是设计模式
- 第 2 层:有很长时间的编程经验,自己写了很多代码,其中用到了设计模式,但是自己却不知道
- 第 3 层:学习过了设计模式,发现自己已经在使用了,并且发现了一些新的模式挺好用的
- 第 4 层:阅读了很多别人写的源码和框架,在其中看到别人设计模式,并且能够领会设计模式的精妙和带来的 好处
- 第 5 层:代码写着写着,自己都没有意识到使用了设计模式,并且熟练的写了出来
# 设计模式介绍
设计模式是程序员在面对同类软件工程设计问题所总结出来的有用的经验,模式不是代码,而是 某类问题的通用解决方案,设计模式(Design pattern)代表了最佳的实践。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
设计模式的本质提高 软件的维护性,通用性和扩展性,并降低软件的复杂度。
《设计模式》 是经典的书,作者是 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides Design(俗称「四人组 GOF」)。
设计模式并不局限于某种语言,Java,PHP,C++ 都有设计模式。
# 设计模式的重要性
软件工程中,设计模式(design pattern)是对软件设计中 普遍存在(反复出现) 的各种问题,所提出的 解决方案。这个术语是由埃里希·伽玛(Erich Gamma)等人在 1990 年代从建筑设计领域引入到计算机科学的。
拿实际工作经历来说,当一个项目开发完后,如果客户 提出增新功能,怎么办?。(可扩展性,使用设计模式,软件具有很好的扩展性)。
如果项目开发完后,原来程序员离职,你接手维护该项目怎么办? (维护性、可读性、规范性)
目前程序员门槛越来越高,一线 IT 公司(大厂),都会问你在实际项目中 使用过什么设计模式,怎样使用的,解决了什么问题。
设计模式在软件中哪里?面向对象(oo)=> 功能模块[设计模式 + 算法(数据结构)] => 框架(使用到多种设计模式) => 架构(服务器集群)。
如果想成为合格软件工程师,那就花时间来研究下设计模式是非常必要的。
# 设计模式的目的
编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战,设计模式是为了让程序(软件),具有更好的:
- 代码重用性(即:相同功能的代码,不用多次编写)
- 可读性(即:编程规范性,便于其他程序员的阅读和理解)
- 可扩展性(即:当需要增加新的功能时,非常的方便,称为可维护)
- 可靠性(即:当我们增加新的功能后,对原来的功能没有影响)
- 可靠性(即:当我们增加新的功能后,对原来的功能没有影响)
设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。正确使用设计模式具有以下优点:
- 可以提高程序员的思维能力、编程能力和设计能力
- 使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期
- 使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强
设计模式解决的是设计不足的问题,但同时也要避免设计过度。一定要牢记简洁原则,要知道设计模式是为了使设计简单,而不是更复杂。如果引入设计模式使得设计变得复杂,只能说我们把简单问题复杂化了,问题本身不需要设计模式。
当然,设计模式只是一个引导。在具体的软件幵发中,必须根据设计的应用系统的特点和要求来恰当选择。对于简单的程序开发,苛能写一个简单的算法要比引入某种设计模式更加容易。但对大项目的开发或者框架设计,用设计模式来组织代码显然更好。
设计模式要活学活用,不要生搬硬套。
需要特别声明的是,在日常应用中,设计模式从来都不是单个设计模式独立使用的。在实际应用中,通常多个设计模式混合使用,你中有我,我中有你。如下图:
分享金句:
- 设计模式包含了面向对象的精髓,「懂了设计模式,你就懂了面向对象分析和设计(OOA/D)的精要」
- Scott Mayers 在其巨著《Effective C++》就曾经说过:C++ 老手和 C++ 新手的区别就是前者手背上有很多伤疤
# 设计模式类型
根据模式是用来完成什么工作来划分,这种方式可分为创建型模式、结构型模式和行为型模式 3 种:
- 创建型模式:用于描述「怎样创建对象」,它的主要特点是「将对象的创建与使用分离」
- 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构
- 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责
共 23 种:
创建型模式(5 种)
- 单例模式(Singleton Pattern):某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式
- 工厂方法模式(FactoryMethod Pattern):定义一个用于创建产品的接口,由子类决定生产什么产品
- 抽象工厂模式(AbstractFactory Pattern):提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品
- 原型模式(Prototype Pattern):将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例
- 建造者模式(Builder Pattern):将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象
以上 5 种创建型模式,除了工厂方法模式属于类创建型模式,其他的全部属于对象创建型模式。
结构型模式(7 种)
- 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作
- 桥接模式(Bridge Pattern):将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现的,从而降低了抽象和实现这两个可变维度的耦合度
- 装饰模式(Decorator Pattern):动态地给对象增加一些职责,即增加其额外的功能
- 组合模式(Composite Pattern):将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性
- 外观模式(Facade Pattern):为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问
- 享元模式(Flyweight Pattern):运用共享技术来有效地支持大量细粒度对象的复用
- 代理模式(Proxy Pattern):为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性
以上 7 种结构型模式,除了适配器模式分为类结构型模式和对象结构型模式两种,其他的全部属于对象结构型模式。
行为型模式(11 种)
- 模板方法模式(Template Method Pattern)模式:定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤
- 命令模式(Command Pattern):将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开
- 访问者模式(Visitor Pattern):在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问
- 迭代器模式(Iterator Pattern):提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示
- 观察者模式(Observer Pattern):多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为
- 中介者模式(Mediator Pattern):定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解
- 备忘录模式(Memento Pattern):在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它
- 解释器模式(Interpreter Pattern):提供如何定义语言的文法,以及对语言句子的解释方法,即解释器
- 状态模式(State Pattern):允许一个对象在其内部状态发生改变时改变其行为能力
- 策略模式(Strategy Pattern):定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户
- 职责链模式(Chain of Responsibility Pattern):把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合
以上 11 种行为型模式,除了模板方法模式和解释器模式是类行为型模式,其他的全部属于对象行为型模式。