目录
- 1. 什么是设计模式?
- 2. 设计模式的七大原则?
- 3. 单例模式
- 4. 三类设计模式
- 5. 什么是单例模式,适用场景以及优缺点?
- 6. 什么是原型模式,适用场景以及优缺点?
- 7. 什么是生成器模式,适用场景以及优缺点?
- 8. 什么是抽象工厂模式,适用场景以及优缺点?
- 9. 什么是工厂方法模式,适用场景以及优缺点?
- 10. 什么是适配器模式,适用场景以及优缺点?
- 11. 什么是桥接模式,适用场景以及优缺点?
- 12. 什么是组合模式,适用场景以及优缺点?
- 13. 什么是装饰模式,适用场景以及优缺点?
- 14. 什么是外观模式,适用场景以及优缺点?
- 15. 什么是享元模式,适用场景以及优缺点?
- 16. 什么是代理模式,适用场景以及优缺点?
- 17. 什么是责任链模式,适用场景以及优缺点?
- 18. 什么是命令模式,适用场景以及优缺点?
- 19. 什么是迭代器模式,适用场景以及优缺点?
- 20. 什么是中介者模式,适用场景以及优缺点?
- 21. 什么是备忘录模式,适用场景以及优缺点?
- 22. 什么是观察者模式,适用场景以及优缺点?
- 23. 什么是状态模式,适用场景以及优缺点?
- 24. 什么是策略模式,适用场景以及优缺点?
- 25. 什么是模板方法模式,适用场景以及优缺点?
- 26. 什么是访问者模式,适用场景以及优缺点?
1. 什么是设计模式?
- 设计模式是一套被反复使用、多数人知晓、经过分类编目、代码设计经验的总结。
- 设计模式与方法或库的使用方式不同, 你很难直接在自己的程序中套用某个设计模式。 模式并不是一段特定的代码, 而是解决特定问题的一般性概念。 你可以根据模式来实现符合自己程序实际所需的解决方案。
- 常常会混淆模式和算法, 因为两者在概念上都是已知特定问题的典型解决方案。 但算法总是明确定义达成特定目标所需的一系列步骤, 而模式则是对解决方案的更高层次描述。 同一模式在两个不同程序中的实现代码可能会不一样。
2. 设计模式的七大原则?
- 开闭原则:对扩展开放,对修改封闭
- 单一职责原则:一个类只负责一个功能领域中的相应职责
- 里氏转换原则:所有引用基类的地方必须能透明的去使用其子类的对象
- 依赖倒转原则:依赖于抽象,不能依赖于具体实现
- 接口依赖原则:类之间的依赖关系应该建立在最小的接口上
- 合成/聚合复用原则:尽量使用合成/聚成,而不是通过继承来达到复用的目的
- 最少知识原则(迪米特法则):一个软件应当尽可能少的和其他实体发生相互作用
3. 单例模式
- 单例模式也分为两种模式:
1.饿汉模式:在类加载时就生成该单例对象- 优点:简单方便;线程安全,调用时反应速度快
- 缺点:会降低启动速度;不关程序是否使用,都会创建该单例对象
- 应用场景:单例对象功能简单,占用内存小,需要频繁使用的时候
public class SingLeton{private static SingLeton instance;private SingLeton(){instance = new SingLeton();}public static SingLeton Instace{get{return instance;}}}
2.懒汉模式:第一次调用时才创建该单例对象
- 优点:在需要时创建,利用率高;提高启动速度
- 缺点:多线程不安全,可能会创建多个实例
- 应用场景:单例对象功能复杂,内存占用大,需要快速启动
public class LazySingleton{private static LSingleton _instance;public static Singleton Instace{get{if (_instance == null){_instance = new Singleton();}return _instance;}}}
4. 三类设计模式
- 创建型模式:提供创建对象的机制, 能够提升已有代码的灵活性和可复用性。
- 结构型模式:这类模式介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效。
- 行为模式:这类模式负责对象间的高效沟通和职责委派。
5. 什么是单例模式,适用场景以及优缺点?
- 单例模式是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。
- 适合应用场景:
- 如果程序中的某个类对于所有客户端只有一个可用的实例
- 如果你需要更加严格地控制全局变量
- 优点:
- 可以保证一个类只有一个实例。
- 获得了一个指向该实例的全局访问节点。
- 仅在首次请求单例对象时对其进行初始化。
- 缺点:
- 违反了单一职责原则。 该模式同时解决了两个问题。
- 单例模式可能掩盖不良设计, 比如程序各组件之间相互了解过多等。
- 该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。
- 单例的客户端代码单元测试可能会比较困难, 因为许多测试框架以基于继承的方式创建模拟对象。 由于单例类的构造函数是私有的, 而且绝大部分语言无法重写静态方法, 所以你需要想出仔细考虑模拟单例的方法。 要么干脆不编写测试代码, 或者不使用单例模式。
public sealed class Singleton{private Singleton() { }private static Singleton _instance;public static Singleton GetInstance(){if (_instance == null){_instance = new Singleton();}return _instance;}public void someBusinessLogic(){// ...}}
6. 什么是原型模式,适用场景以及优缺点?
- 原型模式是一种创建型设计模式, 使你能够复制已有对象, 而又无需使代码依赖它们所属的类。
- 适合应用场景:
- 如果你需要复制一些对象, 同时又希望代码独立于这些对象所属的具体类, 可以使用原型模式。
- 如果子类的区别仅在于其对象的初始化方式, 那么你可以使用该模式来减少子类的数量。 别人创建这些子类的目的可能是为了创建特定类型的对象。
- 优点:
- 可以克隆对象, 而无需与它们所属的具体类相耦合。
- 可以克隆预生成原型, 避免反复运行初始化代码。
- 可以更方便地生成复杂对象。
- 可以用继承以外的方式来处理复杂对象的不同配置。
- 缺点:
- 违克隆包含循环引用的复杂对象可能会非常麻烦。
7. 什么是生成器模式,适用场景以及优缺点?
- 生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。
- 适合应用场景:
- 使用生成器模式可避免 “重叠构造函数 (telescoping constructor)” 的出现。
- 假设你的构造函数中有十个可选参数, 那么调用该函数会非常不方便; 因此, 你需要重载这个构造函数, 新建几个只有较少参数的简化版。 但这些构造函数仍需调用主构造函数, 传递一些默认数值来替代省略掉的参数。
- 当你希望使用代码创建不同形式的产品 (例如石头或木头房屋) 时, 可使用生成器模式。
- 生成器模式让你能分步骤构造产品。 你可以延迟执行某些步骤而不会影响最终产品。 你甚至可以递归调用这些步骤, 这在创建对象树时非常方便。
- 优点:
- 可以分步创建对象, 暂缓创建步骤或递归运行创建步骤。
- 生成不同形式的产品时, 你可以复用相同的制造代码。
- 单一职责原则。 你可以将复杂构造代码从产品的业务逻辑中分离出来。
- 缺点:
- 由于该模式需要新增多个类, 因此代码整体复杂程度会有所增加。
8. 什么是抽象工厂模式,适用场景以及优缺点?
- 抽象工厂模式是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。
- 适合应用场景:
- 如果代码需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。
- 抽象工厂为你提供了一个接口, 可用于创建每个系列产品的对象。 只要代码通过该接口创建对象, 那么你就不会生成与应用程序已生成的产品类型不一致的产品。
- 如果你有一个基于一组抽象方法的类, 且其主要功能因此变得不明确, 那么在这种情况下可以考虑使用抽象工厂模式。
- 在设计良好的程序中, 每个类仅负责一件事。 如果一个类与多种类型产品交互, 就可以考虑将工厂方法抽取到独立的工厂类或具备完整功能的抽象工厂类中。
- 优点:
- 可以确保同一工厂生成的产品相互匹配。
- 可以避免客户端和具体产品代码的耦合。
- 单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
- 开闭原则。 向应用程序中引入新产品变体时, 你无需修改客户端代码。
- 缺点:
- 由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。
9. 什么是工厂方法模式,适用场景以及优缺点?
- 工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。
- 适合应用场景:
- 当你在编写代码的过程中, 如果无法预知对象确切类别及其依赖关系时, 可使用工厂方法。
- 如果你希望用户能扩展你软件库或框架的内部组件, 可使用工厂方法。
- 如果你希望复用现有对象来节省系统资源, 而不是每次都重新创建对象, 可使用工厂方法。
- 优点:
- 可以避免创建者和具体产品之间的紧密耦合。
- 单一职责原则。 你可以将产品创建代码放在程序的单一位置, 从而使得代码更容易维护。
- 开闭原则。 无需更改现有客户端代码, 你就可以在程序中引入新的产品类型。
- 缺点:
- 应用工厂方法模式需要引入许多新的子类, 代码可能会因此变得更复杂。 最好的情况是将该模式引入创建者类的现有层次结构中。
10. 什么是适配器模式,适用场景以及优缺点?
- 适配器模式是一种结构型设计模式, 它能使接口不兼容的对象能够相互合作。
- 适合应用场景:
- 当你希望使用某个类, 但是其接口与其他代码不兼容时, 可以使用适配器类。
- 如果您需要复用这样一些类, 他们处于同一个继承体系, 并且他们又有了额外的一些共同的方法, 但是这些共同的方法不是所有在这一继承体系中的子类所具有的共性。
- 优点:
- 单一职责原则你可以将接口或数据转换代码从程序主要业务逻辑中分离。
- 开闭原则。 只要客户端代码通过客户端接口与适配器进行交互, 你就能在不修改现有客户端代码的情况下在程序中添加新类型的适配器。
- 缺点:
- 代码整体复杂度增加, 因为你需要新增一系列接口和类。 有时直接更改服务类使其与其他代码兼容会更简单。
11. 什么是桥接模式,适用场景以及优缺点?
- 桥接模式是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。
- 适合应用场景:
- 如果你想要拆分或重组一个具有多重功能的庞杂类 (例如能与多个数据库服务器进行交互的类), 可以使用桥接模式。
- 如果你希望在几个独立维度上扩展一个类, 可使用该模式。
- 如果你需要在运行时切换不同实现方法, 可使用桥接模式。
- 优点:
- 可以创建与平台无关的类和程序。
- 客户端代码仅与高层抽象部分进行互动, 不会接触到平台的详细信息。
- 开闭原则。 你可以新增抽象部分和实现部分, 且它们之间不会相互影响。
- 单一职责原则。 抽象部分专注于处理高层逻辑, 实现部分处理平台细节。
- 缺点:
- 对高内聚的类使用该模式可能会让代码更加复杂。
12. 什么是组合模式,适用场景以及优缺点?
- 组合模式是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。
- 适合应用场景:
- 如果你需要实现树状对象结构, 可以使用组合模式。
- 如果你希望客户端代码以相同方式处理简单和复杂元素, 可以使用该模式。
- 优点:
- 可以利用多态和递归机制更方便地使用复杂树结构。
- 开闭原则。 无需更改现有代码, 你就可以在应用中添加新元素, 使其成为对象树的一部分。
- 缺点:
- 对于功能差异较大的类, 提供公共接口或许会有困难。 在特定情况下, 你需要过度一般化组件接口, 使其变得令人难以理解。
13. 什么是装饰模式,适用场景以及优缺点?
- 装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。
- 适合应用场景:
- 如果你希望在无需修改代码的情况下即可使用对象, 且希望在运行时为对象新增额外的行为, 可以使用装饰模式。
- 如果用继承来扩展对象行为的方案难以实现或者根本不可行, 你可以使用该模式。
- 优点:
- 你无需创建新子类即可扩展对象的行为。
- 你可以在运行时添加或删除对象的功能。
- 你可以用多个装饰封装对象来组合几种行为。
- 单一职责原则。 你可以将实现了许多不同行为的一个大类拆分为多个较小的类。
- 缺点:
- 对在封装器栈中删除特定封装器比较困难。
- 实现行为不受装饰栈顺序影响的装饰比较困难。
- 各层的初始化配置代码看上去可能会很糟糕。
14. 什么是外观模式,适用场景以及优缺点?
- 外观模式是一种结构型设计模式, 能为程序库、 框架或其他复杂类提供一个简单的接口。
- 适合应用场景:
- 如果你需要一个指向复杂子系统的直接接口, 且该接口的功能有限, 则可以使用外观模式。
- 如果需要将子系统组织为多层结构, 可以使用外观。
- 优点:
- 你可以让自己的代码独立于复杂子系统。
- 缺点:
- 外观可能成为与程序中所有类都耦合的上帝对象。
15. 什么是享元模式,适用场景以及优缺点?
- 享元模式是一种结构型设计模式, 它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 让你能在有限的内存容量中载入更多对象。
- 适合应用场景:
- 仅在程序必须支持大量对象且没有足够的内存容量时使用享元模式。
- 优点:
- 如果程序中有很多相似对象, 那么你将可以节省大量内存。
- 缺点:
- 你可能需要牺牲执行速度来换取内存, 因为他人每次调用享元方法时都需要重新计算部分情景数据。
- 代码会变得更加复杂。 团队中的新成员总是会问: “为什么要像这样拆分一个实体的状态?”。
16. 什么是代理模式,适用场景以及优缺点?
- 代理模式是一种结构型设计模式, 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。
- 适合应用场景:
- 延迟初始化 (虚拟代理)。 如果你有一个偶尔使用的重量级服务对象, 一直保持该对象运行会消耗系统资源时, 可使用代理模式。
- 访问控制 (保护代理)。 如果你只希望特定客户端使用服务对象, 这里的对象可以是操作系统中非常重要的部分, 而客户端则是各种已启动的程序 (包括恶意程序), 此时可使用代理模式。
- 本地执行远程服务 (远程代理)。 适用于服务对象位于远程服务器上的情形。
- 记录日志请求 (日志记录代理)。 适用于当你需要保存对于服务对象的请求历史记录时。
- 智能引用。 可在没有客户端使用某个重量级对象时立即销毁该对象。
- 优点:
- 你可以在客户端毫无察觉的情况下控制服务对象。
- 如果客户端对服务对象的生命周期没有特殊要求, 你可以对生命周期进行管理。
- 即使服务对象还未准备好或不存在, 代理也可以正常工作。
- 开闭原则。 你可以在不对服务或客户端做出修改的情况下创建新代理。
- 缺点:
- 代码可能会变得复杂, 因为需要新建许多类。
- 服务响应可能会延迟。
17. 什么是责任链模式,适用场景以及优缺点?
- 责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。
- 适合应用场景:
- 当程序需要使用不同方式处理不同种类请求, 而且请求类型和顺序预先未知时, 可以使用责任链模式。
- 当必须按顺序执行多个处理者时, 可以使用该模式。
- 如果所需处理者及其顺序必须在运行时进行改变, 可以使用责任链模式。
- 优点:
- 可以控制请求处理的顺序。
- 单一职责原则。 你可对发起操作和执行操作的类进行解耦。
- 开闭原则。 你可以在不更改现有代码的情况下在程序中新增处理者。
- 缺点:
- 部分请求可能未被处理。
18. 什么是命令模式,适用场景以及优缺点?
- 命令模式是一种行为设计模式, 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作。
- 适合应用场景:
- 如果你需要通过操作来参数化对象, 可使用命令模式。
- 如果你想要将操作放入队列中、 操作的执行或者远程执行操作, 可使用命令模式。
- 如果你想要实现操作回滚功能, 可使用命令模式。
- 优点:
- 单一职责原则。 你可以解耦触发和执行操作的类。
- 开闭原则。 你可以在不修改已有客户端代码的情况下在程序中创建新的命令。
- 你可以实现撤销和恢复功能。
- 你可以实现操作的延迟执行。
- 你可以将一组简单命令组合成一个复杂命令。
- 缺点:
- 代码可能会变得更加复杂, 因为你在发送者和接收者之间增加了一个全新的层次。
19. 什么是迭代器模式,适用场景以及优缺点?
- 迭代器模式是一种行为设计模式, 让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。
- 适合应用场景:
- 当集合背后为复杂的数据结构, 且你希望对客户端隐藏其复杂性时 (出于使用便利性或安全性的考虑), 可以使用迭代器模式。
- 使用该模式可以减少程序中重复的遍历代码。
- 如果你希望代码能够遍历不同的甚至是无法预知的数据结构, 可以使用迭代器模式。
- 优点:
- 单一职责原则。 通过将体积庞大的遍历算法代码抽取为独立的类, 你可对客户端代码和集合进行整理。
- 开闭原则。 你可实现新型的集合和迭代器并将其传递给现有代码, 无需修改现有代码。
- 你可以并行遍历同一集合, 因为每个迭代器对象都包含其自身的遍历状态。
- 相似的, 你可以暂停遍历并在需要时继续。
- 缺点:
- 如果你的程序只与简单的集合进行交互, 应用该模式可能会矫枉过正。
- 对于某些特殊集合, 使用迭代器可能比直接遍历的效率低。
20. 什么是中介者模式,适用场景以及优缺点?
- 中介者模式是一种行为设计模式, 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。
- 适合应用场景:
- 当一些对象和其他对象紧密耦合以致难以对其进行修改时, 可使用中介者模式。
- 当组件因过于依赖其他组件而无法在不同应用中复用时, 可使用中介者模式。
- 如果为了能在不同情景下复用一些基本行为, 导致你需要被迫创建大量组件子类时, 可使用中介者模式。
- 优点:
- 单一职责原则。 你可以将多个组件间的交流抽取到同一位置, 使其更易于理解和维护。
- 开闭原则。 你无需修改实际组件就能增加新的中介者。
- 你可以减轻应用中多个组件间的耦合情况。
- 你可以更方便地复用各个组件。
- 缺点:
- 一段时间后, 中介者可能会演化成为上帝对象。
21. 什么是备忘录模式,适用场景以及优缺点?
- 备忘录模式是一种行为设计模式, 允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。
- 适合应用场景:
- 当你需要创建对象状态快照来恢复其之前的状态时, 可以使用备忘录模式。
- 当直接访问对象的成员变量、 获取器或设置器将导致封装被突破时, 可以使用该模式。
- 优点:
- 你可以在不破坏对象封装情况的前提下创建对象状态快照。
- 你可以通过让负责人维护原发器状态历史记录来简化原发器代码。
- 缺点:
- 如果客户端过于频繁地创建备忘录, 程序将消耗大量内存。
- 负责人必须完整跟踪原发器的生命周期, 这样才能销毁弃用的备忘录。
- 绝大部分动态编程语言 (例如 PHP、 Python 和 JavaScript) 不能确保备忘录中的状态不被修改。
22. 什么是观察者模式,适用场景以及优缺点?
- 观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。
- 适合应用场景:
- 当一个对象状态的改变需要改变其他对象, 或实际对象是事先未知的或动态变化的时, 可使用观察者模式。
- 当应用中的一些对象必须观察其他对象时, 可使用该模式。 但仅能在有限时间内或特定情况下使用。
- 优点:
- 开闭原则。 你无需修改发布者代码就能引入新的订阅者类 (如果是发布者接口则可轻松引入发布者类)。
- 你可以在运行时建立对象之间的联系。
- 缺点:
- 订阅者的通知顺序是随机的。
23. 什么是状态模式,适用场景以及优缺点?
- 状态模式是一种行为设计模式, 让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。
- 适合应用场景:
- 如果对象需要根据自身当前状态进行不同行为, 同时状态的数量非常多且与状态相关的代码会频繁变更的话, 可使用状态模式。
- 如果某个类需要根据成员变量的当前值改变自身行为, 从而需要使用大量的条件语句时, 可使用该模式。
- 当相似状态和基于条件的状态机转换中存在许多重复代码时, 可使用状态模式。
- 优点:
- 单一职责原则。 将与特定状态相关的代码放在单独的类中。
- 开闭原则。 无需修改已有状态类和上下文就能引入新状态。
- 通过消除臃肿的状态机条件语句简化上下文代码。
- 缺点:
- 如果状态机只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作。
24. 什么是策略模式,适用场景以及优缺点?
- 策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。
- 适合应用场景:
-当你想使用对象中各种不同的算法变体, 并希望能在运行时切换算法时, 可使用策略模式。- 如果某个类需要根据成员变量的当前值改变自身行为, 从而需要使用大量的条件语句时, 可使用该模式。
- 当你有许多仅在执行某些行为时略有不同的相似类时, 可使用策略模式。
- 如果算法在上下文的逻辑中不是特别重要, 使用该模式能将类的业务逻辑与其算法实现细节隔离开来。
- 当类中使用了复杂条件运算符以在同一算法的不同变体中切换时, 可使用该模式。
- 优点:
- 你可以在运行时切换对象内的算法。
- 你可以将算法的实现和使用算法的代码隔离开来。
- 你可以使用组合来代替继承。
- 开闭原则。 你无需对上下文进行修改就能够引入新的策略。
- 缺点:
- 如果你的算法极少发生改变, 那么没有任何理由引入新的类和接口。 使用该模式只会让程序过于复杂。
- 客户端必须知晓策略间的不同——它需要选择合适的策略。
- 许多现代编程语言支持函数类型功能, 允许你在一组匿名函数中实现不同版本的算法。 这样, 你使用这些函数的方式就和使用策略对象时完全相同, 无需借助额外的类和接口来保持代码简洁。
25. 什么是模板方法模式,适用场景以及优缺点?
- 模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。
- 适合应用场景:
- 当你只希望客户端扩展某个特定算法步骤, 而不是整个算法或其结构时, 可使用模板方法模式。
- 当多个类的算法除一些细微不同之外几乎完全一样时, 你可使用该模式。 但其后果就是, 只要算法发生变化, 你就可能需要修改所有的类。
- 优点:
- 你可仅允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小。
- 你可将重复代码提取到一个超类中。
- 缺点:
- 部分客户端可能会受到算法框架的限制。
- 通过子类抑制默认步骤实现可能会导致违反里氏替换原则。
- 模板方法中的步骤越多, 其维护工作就可能会越困难。
26. 什么是访问者模式,适用场景以及优缺点?
- 访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。
- 适合应用场景:
- 如果你需要对一个复杂对象结构 (例如对象树) 中的所有元素执行某些操作, 可使用访问者模式。
- 可使用访问者模式来清理辅助行为的业务逻辑。
- 当某个行为仅在类层次结构中的一些类中有意义, 而在其他类中没有意义时, 可使用该模式。
- 优点:
- 开闭原则。 你可以引入在不同类对象上执行的新行为, 且无需对这些类做出修改。
- 单一职责原则。 可将同一行为的不同版本移到同一个类中。
- 访问者对象可以在与各种对象交互时收集一些有用的信息。 当你想要遍历一些复杂的对象结构 (例如对象树), 并在结构中的每个对象上应用访问者时, 这些信息可能会有所帮助。
- 缺点:
- 每次在元素层次结构中添加或移除一个类时, 你都要更新所有的访问者。
- 在访问者同某个元素进行交互时, 它们可能没有访问元素私有成员变量和方法的必要权限。