[TOC]
文章文件夹里有详细文章,
可以点击标题浏览更多内容(附带示例以及实例代码)。
同时欢迎关注我的公众号:迈向架构师,有更多文章分享哦~
↑ 点击查看详细说明 ↑
一个类或者模块只负责单一职责。
软件实体(模块、类、方法等)应该对扩展开放、对修改关闭。
子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏。
另一种说法叫做:按协议设计。
客户端不应该被强迫依赖它不需要的接口。
高层模块不要依赖低层模块。高层模块和低层模块应该通过抽象来互相依赖。除此之外,抽象不要依赖具体实现细节,具体实现细节依赖抽象。
尽量保持简单
不要做过度设计
不要重复自己
又叫最少知识原则(The Least Knowledge Principle)
每个模块只应该了解那些与它关系密切的模块的有限知识。
↑ 点击查看详细说明与示例 ↑
单例模式:一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。
优点:
缺点:
工厂模式:将创建对象移交给工厂来处理。
大部分工厂类都是以“Factory”这个单词结尾的,但也不是必须的,比如 Java 中的 DateFormat、Calender。
除此之外,工厂类中创建对象的方法一般都是 create 开头,比如代码中的 createParser(),
但有的也命名为 getInstance()、createInstance()、newInstance(),
有的甚至命名为 valueOf()(比如 Java String 类的 valueOf() 函数)等等。
这里划分为3个部分:简单工厂、工厂方法、抽象工厂。
↑ 点击查看详细说明与示例 ↑
简单工厂模式描述了一个类,它拥有一个包含大量条件语句的构建方法,可根据方法的参数来选择对何种产品进行初始化并将其返回。
当每个对象的创建逻辑都比较简单的时候,将多个对象的创建逻辑放到一个工厂类中。
优点:
↑ 点击查看详细说明与示例 ↑
工厂方法是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。
Head First 定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类
当每个对象的 创建逻辑 都比较 复杂 的时候,
为了避免设计一个过于庞大的简单工厂类时,将创建逻辑拆分得更细,
让每个对象的创建逻辑独立到各自的工厂类中。
- 当你在编写代码的过程中,如果无法预知对象确切类别及其依赖关系时,可使用工厂方法。
- 如果你希望用户能扩展你软件库或框架的内部组件,可使用工厂方法。
- 如果你希望复用现有对象来节省系统资源,而不是每次都重新创建对象,可使用工厂方法。
优点:
缺点:
在许多设计工作的初期都会使用工厂方法模式(较为简单,而且可以更方便地通过子类进行定制), 随后演化为使用抽象工厂模式、原型模式或生成器模式(更灵活但更加复杂)。
你可以同时使用工厂方法和迭代器模式来让子类集合返回不同类型的迭代器,并使得迭代器与集合相匹配。
工厂方法是模板方法模式的一种特殊形式。同时,工厂方法可以作为一个大型模板方法中的一个步骤。
工厂方法模式建议使用特殊的工厂方法代替对于对象构造函数的直接调用。
对象仍将通过 new 运算符创建,只是该运算符改在工厂的方法中调用罢了。
- 让所有产品都遵循同一接口。该接口必须声明对所有产品都有意义的方法。
- 在创建类中添加一个空的工厂方法。该方法的返回类型必须遵循通用的产品接口。
- 在创建者代码中找到对于产品构造函数的所有引用。将它们依次替换为对于工厂方法的调用,同时将创建产品的代码移入工厂方法。你可能需要在工厂方法中添加临时参数来控制返回的产品类型。
- 现在,为工厂方法中的每种产品编写一个创建者子类,然后在子类中重写工厂方法,并将基本方法中的相关创建代码移动到工厂方法中。
- 如果应用中的产品类型太多,那么为每个产品创建子类并无太大必要,这时你也可以在子类中复用基类中的控制参数。
- 如果代码经过上述移动后,基础工厂方法中已经没有任何代码,你可以将其转变为抽象类。如果基础工厂方法中还有其他语句,你可以将其设置为该方法的默认行为。
↑ 点击查看详细说明与示例 ↑
抽象工厂是一种创建型设计模式,它能创建一系列相关或相互依赖的对象,而无需指定其具体类。
Head First 定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
优点:
缺点:
抽象工厂模式通常基于一组工厂方法,但你也可以使用原型模式来生成这些类的方法。
在许多设计工作的初期都会使用工厂方法模式(较为简单,而且可以更方便地通过子类进行定制), 随后演化为使用抽象工厂模式、原型模式或生成器模式(更灵活但更加复杂)。
你可以同时使用工厂方法和迭代器模式来让子类集合返回不同类型的迭代器,并使得迭代器与集合相匹配。
DI 容器:依赖注入容器(Dependency Injection Container)。
一个工厂类只负责某个类对象或者某一组相关类对象的创建,而 DI 容器负责的是整个应用中所有类对象的创建。
DI 容器底层最基本的设计思路就是基于工厂模式的。
DI 容器相当于一个大的工厂类,负责在程序启动的时候,根据配置(要创建哪些类对象,每个类对象的创建需要依赖哪些其他类对象)事先创建好对象。
当应用程序需要使用某个类对象的时候,直接从容器中获取即可。
正是因为它持有一堆对象,所以这个框架才被称为“容器”。
↑ 点击查看详细说明与示例 ↑
建造者模式(又叫生成器模式、构建者模式):
建造者模式是一种创建型设计模式,使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。
优点:
缺点:
↑ 点击查看详细说明与示例 ↑
原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。
如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同), 在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。
优点:
缺点:
两种具体实现方式:
↑ 点击查看详细说明与示例 ↑
代理模式是一种结构型设计模式,让你能够提供对象的替代品或其占位符。
代理控制着对于原对象的访问,并允许在将请求提交给对象前后进行一些处理。
优点:
缺点:
后续讲到对应的模式时再写
以上为静态代理,
还有动态代理的实现方式:
↑ 点击查看详细说明与示例 ↑
在 GoF 的《设计模式》中,桥接模式是这样定义的:“将抽象和实现解耦,让它们可以独立变化。”
独立的概念可能是:抽象/平台,域/基础设施,前端/后端或接口/实现。
抽象部分(也被称为接口)是一些实体的高阶控制层,该层自身不完成任何具体的工作,它需要将工作委派给实现部分层(也被称为平台)。
这里的抽象和实现是广义上的,而非特指抽象类、实现类。
例子:JDBC 驱动
很多书籍资料中还有另外一种理解方式: “一个类存在两个(或多个)独立变化的维度,通过组合的方式,让这些维度可以独立进行扩展。”
例子:slf4j
slf4j 其中有三个核心概念,logger,appender 和 encoder。
分别指这个日志记录器负责哪个类的日志,日志打印到哪里以及日志打印的格式。
三个纬度上可以有不同的实现,使用者可以在每一纬度上定义多个实现。
优点:
缺点:
↑ 点击查看详细说明与示例 ↑
装饰模式是一种结构型设计模式,允许通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。
装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能。
优点:
缺点:
↑ 点击查看详细说明与示例 ↑
适配器模式是一种结构型设计模式,它能使接口不兼容的对象能够相互合作。
优点:
缺点:
有两种实现方式,一种是类适配器(通过继承),一种是对象适配器(通过组合)
如果接口很多,并且适配器与目标接口定义大部分相同,推荐使用类适配器,复用多,代码量少。
如果接口很多,并且适配器与目标接口定义大部分不同,推荐使用对象适配器,组合结构更加灵活。
↑ 点击查看详细说明与示例 ↑
门面模式(外观模式)是一种结构型设计模式,能为程序库、框架或其他复杂类提供一个简单的接口。
优点:
缺点:
↑ 点击查看详细说明与示例 ↑
组合模式是一种结构型设计模式,组合模式将一组对象组织(Compose)成树形结构,以表示一种”部分-整体”的层次结构。
组合模式让客户端可以统一单个对象和组合对象的处理逻辑。
优点:
缺点:
↑ 点击查看详细说明与示例 ↑
享元模式是一种结构型设计模式。
享元模式顾名思义就是被共享的单元,意图是复用对象,节省内存。
优点:
缺点:
↑ 点击查看详细说明与示例 ↑
观察者模式是一种行为型设计模式。
可以用来定义一种订阅机制,可在对象事件发生时通知多个“观察”该对象的其他对象。
优点:
缺点:
后面讲到再写。
观察者模式有不同的代码实现方式:
有同步阻塞/异步非阻塞的实现方式;
有进程内/跨进程的实现方式。
↑ 点击查看详细说明与示例 ↑
模板方法模式是一种行为设计模式,它在一个超类中定义一个算法骨架,并将某些步骤推迟到子类中实现。
模板方法可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
优点:
缺点:
final
修饰模板方法防止子类重写。回调(Callback)也能起到跟模板模式相同的作用。
同步回调看起来更像模板模式,异步回调看起来更像观察者模式。
↑ 点击查看详细说明与示例 ↑
策略模式是一种行为设计模式。
策略模式定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。使算法的变化独立于使用它们的客户端。
优点:
缺点:
Java 8 开始支持 lambda 方法, 它可作为一种替代策略模式的简单方式。
↑ 点击查看详细说明与示例 ↑
责任链模式是一种行为设计模式。
责任链将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。
这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。
优点:
缺点:
可以使用链表来存储处理器,也可以使用数组来存储处理器。
如果链上的某个处理器能够处理这个请求,可以选择停止传递或者继续传递处理。
↑ 点击查看详细说明与示例 ↑
状态模式是一种行为设计模式
状态模式能在一个对象的内部状态变化时改变其行为,使其看上去就像改变了自身所属的类一样。
与有限状态机的概念紧密相关。
状态机由 3 个部分组成:状态、事件(转移条件)、动作。事件触发状态的转移及动作的执行。
优点:
缺点:
其他实现方法:
分支逻辑法: 直接利用 if 逻辑或者 switch 分支逻辑,直接写状态转移的代码。适合简单直接的状态机。
查表法: 通过二维数组来表示状态转移图,能极大地提高代码的可读性和可维护性。适合状态较多、转移复杂的状态机。
↑ 点击查看详细说明与示例 ↑
迭代器模式是一种行为设计模式,
也叫作游标模式(Cursor Design Pattern)
能在不暴露集合底层表现形式(数组、链表、树、图、跳表等)的情况下遍历集合中所有的元素。
优点:
缺点:
↑ 点击查看详细说明与示例 ↑
访问者模式是一种行为设计模式。
它允许一个或者多个操作应用到一组对象上,解耦操作和对象本身。
访问者主要目的在于:在单分派的语言中实现双分派的功能 (Java是单分派的)。
优点:
缺点:
↑ 点击查看详细说明与示例 ↑
备忘录模式是一种行为设计模式,
它允许在不暴露对象实现细节(封装原则)的情况下保存和恢复对象之前的状态。
优点:
缺点:
可以灵活的各种实现,只要不破坏原有封装即可,如:
也可以针对备忘录进行优化,如利用**“增量备份”**的方式来节省内存消耗。
实现时要注意深度拷贝的问题。
↑ 点击查看详细说明与示例 ↑
命令模式是一种行为设计模式,
它可以将请求转换为一个包含与请求相关的所有信息的独立对象。
转换让你能根据不同的请求将方法参数化,并且能够支持排队、延迟执行、记录日志、撤销等附加控制功能。
优点:
缺点:
↑ 点击查看详细说明与示例 ↑
解释器模式是一种行为设计模式。
解释器模式为某个语言定义它的语法表示,并定义一个解释器用来处理这个语法。
优点:
缺点:
解释器模式代码实现的核心思想就是将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。
解释器模式的代码实现比较灵活,没有固定的模板,在我的示例中的做法大体可以拆分为:
↑ 点击查看详细说明与示例 ↑
中介者模式是一种行为设计模式,能减少对象之间混乱无序的依赖关系。
该模式会限制对象之间的直接交互,迫使它们通过一个中介者对象进行合作(中转与协调)。
优点:
缺点:
创建型设计模式主要解决对象创建
问题,
结构型设计模式主要解决类或对象的组合或组装
问题,
行为型设计模式主要解决的就是类或对象之间的交互
问题。
实际上,设计模式要干的事情就是解耦,
创建型模式是将创建和使用
代码解耦 ,
结构型模式是将不同功能
代码解耦,
行为型模式是将不同行为
代码解耦。
设计原则和思想比设计模式更加普适和重要。
掌握了代码的设计原则和思想,我们能更清楚的了解为什么要用某种设计模式,就能更恰到好处地应用设计模式。
同时遵循 KISS 原则,怎么简单怎么来,就是最好的设计。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。