23种设计模式知识点整理,建议收藏
Posted 菜根老谭
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23种设计模式知识点整理,建议收藏相关的知识,希望对你有一定的参考价值。
设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。
1995 年,GoF(Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了 23 种设计模式,从此树立了软件设计模式领域的里程碑,人称「GoF设计模式」。
这 23 种设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性,以及类的关联关系和组合关系的充分理解。
当然,软件设计模式只是一个引导,在实际的软件开发中,必须根据具体的需求来选择:
对于简单的程序,可能写一个简单的算法要比引入某种设计模式更加容易;
但是对于大型项目开发或者框架设计,用设计模式来组织代码显然更好。
为了让大家快速的、整体的学习和使用设计模式,老谭整理了23种设计模式的重要知识点,希望对您有所帮助。enjoy~
发送私信“设计模式”,获取可编辑的类图文件。
1、单例模式(Singleton Pattern)
定义
Ensure a class has only one instance, and provide a global point of access to it.
某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
类图
使用场景
● 要求生成唯一序列号的环境;
● 在整个项目中需要一个共享访问点或共享数据,例如一个 Web 页面上的计数 器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确 保证线程安全的;
● 创建一个对象需要消耗的资源过多,如要访问 IO 和数据库等资源;
● 需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式 (当然,也可以直接声明为 static 的方式)。
2、工厂模式(Factory Pattern)
定义
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer intantiation to subclasses.
定义了一个创建对象的接口,由子类来决定详细实例化那个对象。工厂方法模式让类的实例化转移到子类中来推断。
类图
简单工厂模式一个模块仅需要一个工厂类,没有必要把它产生出来,使用静态的方法
多个工厂类每个人种(具体的产品类)都对应了一个创建者,每个创建者独立负责创建对应的 产品对象,非常符合单一职责原则
代替单例模式单例模式的核心要求就是在内
延迟初始化ProductFactory 负责产品类对象的创建工作,并且通过prMap 变量产生一个缓 存,对需要再次被重用的对象保留
使用场景
jdbc 连接数据库,硬件访问,降低对象的产生和销毁
3、抽象工厂(Abstract Factory Pattern)
定义
Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类 – 客户端不必指定产品的具体类型,创建多个产品
族 中的产品对象
类图
使用场景
一个对象族(或是一组没有任何关系的对象)都有相同的约束。涉及不同操作系统的时候,都可以考虑使用抽象工厂模式
4、建造者模式(Builder Pattern)
定义
Seperate the constraction of a complex object from its representation so that the same construction process can create different representations.
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
类图
● Product 产品类通常是实现了模板方法模式,也就是有模板方法和基本方法,例子中的 BenzModel 和 BMWModel 就属于产品类。
● Builder 抽象建造者规范产品的组建,一般是由子类实现。例子中的 CarBuilder 就属于抽象建造者。
● ConcreteBuilder 具体建造者实现抽象类定义的所有方法,并且返回一个组建好的对象。例子中的 BenzBuilder 和 BMWBuilder 就属于具体建造者。
● Director 导演类负责安排已有模块的顺序,然后告诉 Builder 开始建造
使用场景
● 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。
● 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时, 则可以使用该模式。
● 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使 用建造者模式非常合适。
建造者模式与工厂模式的不同
建造者模式最主要的功能是基本方法的调用顺序安排,这些基本方法已经实现了, 顺序不同产生的对象也不同;工厂方法则重点是创建,创建零件是它的主要职责,组装顺序则不是它关
5、代理模式(Proxy Pattern)
定义
Provide a surrogate or placeholder for another object to control access to it
为其
他 对象提供一种代理以控制对这个对象的访问
类图
● Subject 抽象主题角色抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要 求。
● RealSubject 具体主题角色也叫做被委托角色、被代理角色。它才是冤大头,是业务逻辑的具体执行者。
● Proxy 代理主题角色也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法 限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后 处理工作。
普通代理和强制代理
普通代理就是我们要知道代理的存在,也就是类似的 GamePlayerProxy 这个类的 存在,然后才能访问;强制代理则是调用者直接调用真实角色,而不用关心代理是否存在,其代理的产生 是由真实角色决定的。
普通代理: 在该模式下,调用者只知代理而不用知道真实的角色是谁,屏蔽了真实角色的变更 对高层模块的影响,真实的主题角色想怎么修改就怎么修改,对高层次的模块没有 任何的影响,只要你实现了接口所对应的方法,该模式非常适合对扩展性要求较高 的场合。强制代理:强制代理的概念就是要从真实角色查找到代理角色,不允许直接访问真实角色。高 层模块只要调用 getProxy 就可以访问真实角色的所有方法,它根本就不需要产生 一个代理出来,代理的管理已经由真实角色自己完成。
动态代理: 根据被代理的接口生成所有的方法,也就是说给定一个接口,动态代理会宣称“我 已经实现该接口下的所有方法了”。两条独立发展的线路。动态代理实现代理的职责,业务逻辑 Subject 实现相关的逻 辑功能,两者之间没有必然的相互耦合的关系。通知 Advice 从另一个切面切入, 最终在高层模块也就是 Client 进行耦合,完成逻辑的封装任务。
6、模板方法模式(Template Method Pattern)
定义
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain stops of an algorithm without chaning the algorithm's structure
定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
类图
AbstractClass 叫做抽象模板,它的方法分为两类:
● 基本方法基本方法也叫做基本操作,是由子类实现的方法,并且在模板方法被调用。
● 模板方法可以有一个或几个,一般是一个具体方法,也就是一个框架,实现对基本方法的调 度,完成固定的逻辑。注意:为了防止恶意的操作,一般模板方法都加上 final 关键字,不允许被覆 写。具体模板:ConcreteClass1 和ConcreteClass2 属于具体模板,实现父类所定义的 一个或多个抽象方法,也就是父类定义的基本方法在子类中得以实现
使用场景
● 多个子类有公有的方法,并且逻辑基本相同时。
● 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由 各个子类实现。
● 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然 后通过钩子函数约束其行为。
7、原型模式(Prototype Pattern)
定义
Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
采用复制已有对象实例来产生新的对象实例。
类图
使用原型模式的优点
● 性能优良原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是 要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
● 逃避构造函数的约束这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的
使用场景
● 资源优化场景类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
● 性能和安全要求的场景通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模 式。
● 一个对象多个修改者的场景一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以 考虑使用原型模式拷贝多个对象供调用者使用。
浅拷贝和深拷贝
深拷贝:对私有的类变量进行独立的拷贝如:thing.arrayList = (ArrayList)this.arrayList.clone();
8、中介者模式(Mediator Pattern)
定义
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
定义一个对象,这个对象封装了一组对象的交互。中介者模式通过使各个对象之间不用显示交互,来解耦各个对象,并且 中介者 模式允许 对象独立的改变他的交互。
类图
● Mediator 抽象中介者角色抽象中介者角色定义统一的接口,用于各同事角色之间的通信。
● Concrete Mediator 具体中介者角色具体中介者角色通过协调各同事角色实现协作行为,因此它必须依赖于各个同事角 色。
● Colleague 同事角色每一个同事角色都知道中介者角色,而且与其他的同事角色通信的时候,一定要通 过中介者角色协作。
每个同事类的行为分为两种:
一种是同事本身的行为,比如改 变对象本身的状态,处理自己的行为等,这种行为叫做自发行为(Self- Method),与其他的同事类或中介者没有任何的依赖;
第二种是必须依赖中介者 才能完成的行为,叫做依赖方法(Dep-Method)。
使用场景
中介者模式适用于多个对象之间紧密耦合的情况,紧密耦合的标准是:在类图中出 现了蜘蛛网状结构,即每个类都与其他的类有直接的联系。
9、命令模式(Command Pattern)
定义
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能
类图
● Receive 接收者角色该角色就是干活的角色,命令传递到这里是应该被执行的,具体到我们上面的例子 中就是 Group 的三个实现类(需求组,美工组,代码组)。
● Command 命令角色需要执行的所有命令都在这里声明。
● Invoker 调用者角色接收到命令,并执行命令。在例子中,我(项目经理)就是这个角色。
使用场景
认为是命令的地方就可以采用命令模式,例如,在 GUI 开发中,一个按钮的点击 是一个命令,可以采用命令模式;模拟 DOS 命令的时候,当然也要采用命令模式;触发-反馈机制的处理等。
10、责任链模式(Chain of Responsibility Pattern)
定义
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
类图
抽象的处理者实现三个职责:
一是定义一个请求的处理方法 handleMessage,唯一对外开放的方法;
二是定义一个链的编排方法 setNext,设置下一个处理者;
三是定义了具体的请求者必须实现的两个方法:定义自己能够处理的级别 getHandlerLevel 和具体的处理任务 echo。
注意事项
链中节点数量需要控制,避免出现超长链的情况,一般的做法是在 Handler 中设置 一个最大节点数量,在 setNext 方法中判断是否已经是超过其阈值,超过则不允许 该链建立,避免无意识地破坏系统性能。
11、装饰模式(Decorator Pattern)
定义
Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
类图
● Component 抽象构件Component 是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原 始的对象,如上面的成绩单。注意:在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当 Component 抽象构件。
● ConcreteComponent 具体构件ConcreteComponent 是最核心、最原始、最基本的接口或抽象类的实现,你要装 饰的就是它。
● Decorator 装饰角色一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象 的方法呀,在它的属性里必然有一个 private 变量指向 Component 抽象构件。
● 具体装饰角色ConcreteDecoratorA 和 ConcreteDecoratorB 是两个具体的装饰类,你要把你最核 心的、最原始的、最基本的东西装饰成其他东西,上面的例子就是把一个比较平庸 的成绩单装饰成家长认可的成绩单。
使用场景
● 需要扩展一个类的功能,或给一个类增加附加功能。
● 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
● 需要为一批的兄弟类进行改装或加装功能,当然是首选装饰模式。
12、策略模式(Strategy Pattern)
定义
Define a family of algorithms, encapsulate each one, and make them interchangeable.
定义一组算法,将每个算法都封装起来,并且使
他们 之间可以互换
类图
● Context 封装角色它也叫做上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访 问,封装可能存在的变化。
● Strategy 抽象策略角色策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属 性。各位看官可能要问了,类图中的 AlgorithmInterface 是什么意思,嘿嘿, algorithm 是“运算法则”的意思,结合起来意思就明白了吧。
● ConcreteStrategy 具体策略角色(多个)实现抽象策略中的操作,该类含有具体的算法。
使用场景
● 多个类只有在算法或行为上稍有不同的场景。
● 算法需要自由切换的场景。
● 需要屏蔽算法规则的场景。
注意事项:具体策略数量超过 4 个,则需要考虑使用混合模式
13、适配器模式(Adapter Pattern)
定义
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that could't otherwise because of incompatible interfaces.
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
类图
类适配器
● Target 目标角色该角色定义把其他类转换为何种接口,也就是我们的期望接口,例子中的 IUserInfo 接口就是目标角色。
● Adaptee 源角色你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类 或对象,经过适配器角色的包装,它会成为一个崭新、靓丽的角色。
● Adapter 适配器角色适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要 新建立的,它的职责非常简单:把
对象适配器和类适配器的区别:
类适配器是类间继承,对象适配器是对象的合成关系,也可以说是类的关联关系, 这是两者的根本区别。(实际项目中对象适配器使用到的场景相对比较多)。
使用场景
你
注意事项:详细设计阶段不要考虑使用适配器模式,使用主要场景为扩展应用中。
14、迭代器模式(Iterator Pattern)
定义
Provide a way to access the elements of an aggregate object sequencially without exposing its underlying represetation.
它提供一种方法访问一个容器对 象中各个元素,而又不需暴露该对象的内部细节。
类图
● Iterator 抽象迭代器抽象迭代器负责定义访问和遍历元素的接口,而且基本上是有固定的 3 个方法:first()获得第一个元素,next()访问下一个元素,isDone()是否已经访问到底部(Java 叫做 hasNext()方法)。
● ConcreteIterator 具体迭代器具体迭代器角色要实现迭代器接口,完成容器元素的遍历。
● Aggregate 抽象容器容器角色负责提供创建具体迭代器角色的接口,必然提供一个类似 createIterator() 这样的方法,在 Java 中一般是 iterator()方法。
● Concrete Aggregate 具体容器具体容器实现容器接口定义的方法,创建出容纳迭代器的对象。ps:迭代器模式已经被淘汰,java 中已经把迭代器运用到各个聚集类(collection)中了,使用 java 自带的迭代器就已经满足我们的需求了。
15、组合模式(Composite Pattern)
定义
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对于单个对象和组合对象的使用具有一致性。
类图
● Component 抽象构件角色定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性,比如我们 例子中的 getInfo 就封装到了抽象类中。
● Leaf 叶子构件叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。
● Composite 树枝构件树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构。
使用场景
● 维护和展示部分-整体关系的场景,如树形菜单、文件和文件夹管理。
● 从一个整体中能够独立出部分模块或功能的场景。
注意
只要是树形结构,就考虑使用组合模式。
16、观察者模式(Observer Pattern)
定义
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于 它的对象都会得到通知并被自动更新。
类图
● Subject 被观察者定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽 象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观 察者。
● Observer 观察者观察者接收到消息后,即进行 update(更新方法)操作,对接收到的信息进行处 理。
● ConcreteSubject 具体的被观察者定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
● ConcreteObserver 具体的观察者每个观察在接收到消息后的处理反应是不同,各个观察者有自己的处理逻辑。
使用场景
● 关联行为场景。需要注意的是,关联行为是可拆分的,而不是“组合”关系。
● 事件多级触发场景。
● 跨系统的消息交换场景,如消息队列的处理机制。
注意
● 广播链的问题在一个观察者模式中最多出现一个对象既是观察者也是被观察者,也就是说消息最 多转发一次(传递两次)。
● 异步处理问题观察者比较多,而且处理时间比较长,采用异步处理来考虑线程安全和队列的问 题。
17、门面模式(Facade Pattern)
定义
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
要求一 个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个 高层次的接口,使得子系统更易于使用。
类图
● Facade 门面角色客户端可以调用这个角色的方法。此角色知晓子系统的所有功能和责任。一般情况 下,本角色会将所有从客户端发来的请求委派到相应的子系统去,也就说该角色没 有实际的业务逻辑,只是一个委托类。
● subsystem 子系统角色可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类 的集合。子系统并不知道门面的存在。对于子系统而言,门面仅仅是另外一个客户 端而已。
使用场景
● 为一个复杂的模块或子系统提供一个供外界访问的接口
● 子系统相对独立——外界对子系统的访问只要黑箱操作即可
● 预防低水平人员带来的风险扩散
注意
●一个子系统可以有多个门面
●门面不参与子系统内的业务逻辑
18、备忘录模式(Memento Pattern)
定义
Without violating encapsulation. capture and externalize an object's internal state so that the object can be restored to this state later.
在不破坏封装性的前提 下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该 对象恢复到原先保存的状态。
类图
● Originator 发起人角色记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备 忘录数据。
● Memento 备忘录角色(简单的 javabean)负责存储 Originator 发起人对象的内部状态,在需要的时候提供发起人需要的内部 状态。
● Caretaker 备忘录管理员角色(简单的 javabean)对备忘录进行管理、保存和提供备忘录。
几种备忘录模式
clone 方式备忘录:
● 发起人角色融合了发起人角色和备忘录角色,具有双重功效
多状态的备忘录模式
● 增加了一个 BeanUtils 类,其中 backupProp 是把发起人的所有属性值转换到 HashMap 中,方便备忘录角色存储。restoreProp 方法则是把HashMap 中的值返 回到发起人角色中。
多备份的备忘录:略封装得更好一点:保证只能对发起人可读
●建立一个空接口 IMemento——什么方法属性都没有的接口,然后在发起人 Originator 类中建立一个内置类(也叫做类中类)Memento 实现IMemento 接口, 同时也实现自己的业务逻辑。
使用场景
● 需要保存和恢复数据的相关状态场景。
● 提供一个可回滚(rollback)的操作。
● 需要监控的副本场景中。
● 数据库连接的事务管理就是用的备忘录模式。
注意
●备忘录的生命期
●备忘录的性能不要在频繁建立备份的场景中使用备忘录模式(比如一个for 循环中)。
19、访问者模式(Visitor Pattern)
定义
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
类图
● Visitor——抽象访问者抽象类或者接口,声明访问者可以访问哪些元素,具体到程序中就是 visit 方法的 参数定义哪些对象是可以被访问的。
● ConcreteVisitor——具体访问者它影响访问者访问到一个类后该怎么干,要做什么事情。
● Element——抽象元素接口或者抽象类,声明接受哪一类访问者访问,程序上是通过 accept 方法中的参 数来定义的。
● ConcreteElement——具体元素实现 accept 方法,通常是 visitor.visit(this),基本上都形成了一种模式了。
● ObjectStruture——结构对象元素产生者,一般容纳在多个不同类、不同接口的容器,如 List、Set、Map 等, 在项目中,一般很少抽象出这个角色。
使用场景
● 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些 依赖于其具体类的操作,也就说是用迭代器模式已经不能胜任的情景。
● 需要对一个对象结构中的对象进行很多不同并且不相关的操作,而你想避免让这 些操作“污染”这些对象的类。
20、状态模式(State Pattern)
定义
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
当一个对象内在状态改变时允许其改变行 为,这个对象看起来像改变了其类。
类图
● State——抽象状态角色接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换。
● ConcreteState——具体状态角色每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,通俗地 说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。
● Context——环境角色定义客户端需要的接口,并且负责具体状态的切换。
使用场景
● 行为随状态改变而改变的场景这也是状态模式的根本出发点,例如权限设计,人员的状态不同即使执行相同的行 为结果也会不同,在这种情况下需要考虑使用状态模式。
● 条件、分支判断语句的替代者
注意
状态模式适用于当某个对象在它的状态发生改变时,它的行为也随着发生比较大的 变化,也就是说在行为受状态约束的情况下可以使用状态模式,而且使用时对象的 状态最好不要超过 5 个。
21、解释器模式(Interpreter Pattern)
定义
Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
类图
● AbstractExpression——抽象解释器具体的解释任务由各个实现类完成,具体的解释器分别由 TerminalExpression 和 Non-terminalExpression 完成。
● TerminalExpression——终结符表达式实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表 达式,但有多个实例,对应不同的终结符。具体到我们例子就是 VarExpression 类,表达式中的每个终结符都在栈中产生了一个 VarExpression 对象。
● NonterminalExpression——非终结符表达式文法中的每条规则对应于一个非终结表达式,具体到我们的例子就是加减法规则分 别对应到 AddExpression 和 SubExpression 两个类。非终结符表达式根据逻辑的 复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
● Context——环境角色具体到我们的例子中是采用 HashMap 代替。
使用场景
● 重复发生的问题可以使用解释器模式
● 一个简单语法需要解释的场景
注意
尽量不要在重要的模块中使用解释器模式,否则维护会是一个很大的问题。
22、享元模式(Flyweight Pattern)
定义
Use sharing to support large numbers of fine-grained objects effciently.
使用共享对象可有效地支持大量的细粒度的对象。
类图
对象的信息分为两个部分:内部状态(intrinsic)与外部状态(extrinsic)。
● 内部状态内部状态是对象可共享出来的信息,存储在享元对象内部并且不会随环境改变而改 变。
● 外部状态外部状态是对象得以依赖的一个标记,是随环境改变而改变的、不可以共享的状 态。
● Flyweight——抽象享元角色它简单地说就是一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口 或实现。
● ConcreteFlyweight——具体享元角色具体的一个产品类,实现抽象角色定义的业务。该角色中需要注意的是内部状态处 理应该与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态, 这是绝对不允许的。
● unsharedConcreteFlyweight——不可共享的享元角色不存在外部状态或者安全要求(如线程安全)不能够使用共享技术的对象,该对象 一般不会出现在享元工厂中。
● FlyweightFactory——享元工厂职责非常简单,就是构造一个池容器,同时提供从池中获得对象的方法。
使用场景
● 系统中存在大量的相似对象。
● 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对 象没有特定身份。
● 需要缓冲池的场景。
注意
● 享元模式是线程不安全的,只有依靠经验,在需要的地方考虑一下线程安全,在 大部分场景下不用考虑。对象池中的
● 性能安全:外部状态最好以 java 的基本类型作为标志,如 String,int,可以提 高效率。
23、桥梁模式(Bridge Pattern)
定义
Decouple an abstraction from its implementation so that the two can vary independently
将抽象和实现解耦,使得两者可以独立地变化。
类图
● Abstraction——抽象化角色它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色 一般是抽象类。
● Implementor——实现化角色它是接口或者抽象类,定义角色必需的行为和属性。
● RefinedAbstraction——修正抽象化角色它引用实现化角色对抽象化角色进行修正。
● ConcreteImplementor——具体实现化角色它实现接口或抽象类定义的方法和属性。
使用场景
● 不希望或不适用使用继承的场景
● 接口或抽象类不稳定的场景
● 重用性要求较高的场景
注意
发现类的继承有 N 层时,可以考虑使用桥梁模式。桥梁模式主要考虑如何拆分抽 象和实现。
发送私信“设计模式”,获取可编辑的类图文件。
正文部分
同时,微信为菜根老谭开通了视频号,配合着一些短视频,讲讲产品研发的那点事,分析产品研发过程中出现的问题以及思考。
点击“阅读原文”,获取《程序员的思维修炼》专栏文章
以上是关于23种设计模式知识点整理,建议收藏的主要内容,如果未能解决你的问题,请参考以下文章
熬夜爆肝!C++核心进阶知识点汇总整理万字干货预警 建议收藏
期末复习c++知识点大回顾,八篇文章让你永不破防(建议收藏)