结构型设计模式
一 适配器模式
适配器模式是一种结构型设计模式,它能使接口不兼容的对象相互合作。适配器模式主要有类适配器模式、对象适配器模式和接口适配器模式。
类适配器模式
类适配器模式通过继承来实现适配,适配器类继承自被适配者类并实现目标接口。
说明
- 目标接口(
Target
):定义了客户端所期望的接口方法request()
。 - 被适配者类(
Adaptee
):包含了客户端需要使用的特定功能方法specificRequest()
。 - 适配器类(
ClassAdapter
):继承自Adaptee
类并实现Target
接口,在request()
方法中调用Adaptee
类的specificRequest()
方法,完成适配。 - 客户端类(
Client
):依赖于Target
接口,通过调用Target
接口的request()
方法来使用适配后的功能。
对象适配器模式
对象适配器模式通过组合来实现适配,适配器类持有被适配者类的对象。
说明
- 目标接口(
Target
):同上述类适配器模式中的Target
接口,定义了客户端期望的接口方法request()
。 - 被适配者类(
Adaptee
):包含特定功能方法specificRequest()
。 - 适配器类(
ObjectAdapter
):实现Target
接口,持有一个Adaptee
类的对象,在request()
方法中调用该对象的specificRequest()
方法,实现适配。 - 客户端类(
Client
):依赖于Target
接口,通过调用Target
接口的request()
方法使用适配后的功能。
接口适配器模式(缺省适配器模式)
接口适配器模式适用于当一个接口中有多个方法,但客户端只需要使用其中一部分方法的情况。通过创建一个抽象类实现该接口,并为接口的每个方法提供默认实现,客户端可以继承该抽象类并选择性地重写需要的方法。
说明
- 目标接口(
TargetInterface
):定义了多个方法(method1()
、method2()
、method3()
)。 - 抽象适配器类(
AbstractAdapter
):实现TargetInterface
接口,并为接口中的每个方法提供默认实现。 - 具体客户端类(
ConcreteClient
):继承自AbstractAdapter
类,选择性地重写需要的方法(这里重写了method2()
)。 - 客户端类(
Client
):依赖于TargetInterface
接口,通过ConcreteClient
类来使用适配后的功能。
二 桥接模式
桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化。
代码说明
- 实现化接口(
Implementor
):定义了实现部分的接口,声明了operationImpl()
方法,具体的实现类需要实现该方法。 - 具体实现化类(
ConcreteImplementorA
和ConcreteImplementorB
):实现了Implementor
接口,提供了具体的实现逻辑。 - 抽象化类(
Abstraction
):包含一个指向Implementor
接口的引用,通过构造函数注入实现化对象。定义了operation()
方法,该方法会调用实现化对象的operationImpl()
方法。 - 扩充抽象化类(
RefinedAbstraction
):继承自Abstraction
类,可以对operation()
方法进行扩展。 - 客户端类(
Client
):依赖于Abstraction
类,通过调用Abstraction
类的operation()
方法来使用桥接模式的功能。
模式解释
桥接模式通过将抽象部分(Abstraction
)和实现部分(Implementor
)分离,使得它们可以独立地变化。客户端只需要与抽象部分交互,而抽象部分通过组合的方式与实现部分协作,这样在需要扩展抽象部分或实现部分时,不会影响到对方。例如,当需要添加新的实现类时,只需要实现 Implementor
接口;当需要扩展抽象部分的功能时,只需要继承 Abstraction
类。
三 装饰模式
装饰模式UML说明:
-
抽象组件(Component)
- 定义对象的接口规范
- 使用抽象类表示(带
<<abstract>>
标签)
-
具体组件(ConcreteComponent)
- 实现抽象组件接口
- 定义核心功能
-
抽象装饰器(Decorator)
- 继承抽象组件
- 包含组件引用(组合关系)
- 实现接口方法并调用组件功能
- 新增装饰行为预留扩展点
-
具体装饰器(ConcreteDecorator)
- 继承抽象装饰器
- 实现具体装饰逻辑
- 添加额外功能(如
addedBehaviorA
)
-
客户端(Client)
- 通过抽象组件接口编程
- 动态组合装饰器链
模式特点:
- 动态扩展:可以在运行时添加/删除装饰器
- 松耦合:装饰器与组件实现解耦
- 透明性:客户端无需区分装饰器和组件
- 灵活组合:多个装饰器可按任意顺序组合
典型应用场景:
- Java IO流(如
BufferedInputStream
装饰FileInputStream
) - 日志增强
- 权限控制
- 动态代理(与装饰模式原理相似)
该模式通过组合替代继承,避免了类爆炸问题,同时保持了良好的扩展性。
四 组合模式
组合模式是一种结构型设计模式,它允许你将对象组合成树形结构以表示“部分 - 整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
代码说明
- 抽象组件类(
Component
):- 定义了组件的抽象接口,包含
operation()
方法,用于执行组件的操作;add()
方法,用于向组合节点中添加子组件;remove()
方法,用于从组合节点中移除子组件;getChild()
方法,用于获取组合节点中的指定子组件。 - 该类是抽象类,叶子节点和组合节点都需要继承该类。
- 定义了组件的抽象接口,包含
- 叶子节点类(
Leaf
):- 继承自
Component
类,实现了operation()
方法,代表树形结构中的叶子节点,没有子组件,所以add()
、remove()
和getChild()
方法可以不做实际操作或者抛出异常。
- 继承自
- 组合节点类(
Composite
):- 继承自
Component
类,包含一个children
列表,用于存储子组件。 - 实现了
operation()
方法,通常会遍历所有子组件并调用它们的operation()
方法;add()
方法用于将子组件添加到children
列表中;remove()
方法用于从children
列表中移除指定的子组件;getChild()
方法用于从children
列表中获取指定索引的子组件。
- 继承自
- 客户端类(
Client
):- 依赖于
Component
类,通过调用Component
类的方法来操作树形结构,无需关心操作的是叶子节点还是组合节点。
- 依赖于
模式解释
组合模式通过将叶子节点和组合节点统一抽象为 Component
类,使得客户端可以以一致的方式处理单个对象和组合对象。在树形结构中,组合节点可以包含叶子节点和其他组合节点,形成递归的层次结构。客户端可以通过组合节点的 add()
和 remove()
方法动态地构建和修改树形结构。
五 外观模式
外观模式是一种结构型设计模式,它为子系统中的一组接口提供一个统一的高层接口,使得子系统更易于使用。
代码说明
- 子系统类(
SubsystemA
、SubsystemB
、SubsystemC
):- 每个子系统类都有自己的特定操作方法,例如
operationA()
、operationB()
和operationC()
,这些方法实现了子系统的具体功能。
- 每个子系统类都有自己的特定操作方法,例如
- 外观类(
Facade
):- 包含对各个子系统类的引用(
subsystemA
、subsystemB
、subsystemC
)。 - 构造函数用于初始化这些子系统对象。
operation()
方法是外观类提供的统一接口,它会调用各个子系统的操作方法,将子系统的复杂操作封装起来,对外提供一个简单的接口。
- 包含对各个子系统类的引用(
- 客户端类(
Client
):- 依赖于外观类
Facade
,通过调用外观类的operation()
方法来使用子系统的功能,而不需要直接与各个子系统类进行交互。
- 依赖于外观类
模式解释
外观模式的核心思想是将子系统的复杂性隐藏起来,为客户端提供一个简单的接口。客户端只需要与外观类进行交互,而不需要了解子系统的具体实现细节。这样可以降低客户端与子系统之间的耦合度,提高系统的可维护性和可扩展性。
六 享元模式
享元模式是一种结构型设计模式,它通过共享对象来减少内存使用和提高性能,尤其适用于存在大量细粒度对象的场景。
代码说明
- 抽象享元类(
Flyweight
):- 定义了享元对象的接口,包含一个
operation()
方法,该方法接受一个外部状态参数extrinsicState
,用于执行享元对象的操作。
- 定义了享元对象的接口,包含一个
- 具体享元类(
ConcreteFlyweight
):- 实现了
Flyweight
接口,包含一个内部状态intrinsicState
,该状态在对象创建时初始化,并且在对象的生命周期内不会改变。 ConcreteFlyweight
类的构造函数用于初始化内部状态,operation()
方法会结合内部状态和传入的外部状态执行具体的操作。
- 实现了
- 享元工厂类(
FlyweightFactory
):- 包含一个
flyweights
映射,用于存储已经创建的享元对象,键为对象的内部状态。 - 构造函数用于初始化
flyweights
映射。 getFlyweight()
方法根据传入的键查找对应的享元对象,如果对象已经存在则直接返回,否则创建一个新的享元对象并存储在flyweights
映射中,然后返回该对象。
- 包含一个
- 客户端类(
Client
):- 依赖于
FlyweightFactory
类,通过调用FlyweightFactory
的getFlyweight()
方法来获取享元对象,并调用享元对象的operation()
方法。
- 依赖于
模式解释
享元模式的核心思想是将对象的状态分为内部状态和外部状态。内部状态是对象共享的部分,存储在享元对象中;外部状态是对象变化的部分,由客户端在使用时传入。通过享元工厂类来管理和共享享元对象,避免了大量重复对象的创建,从而减少了内存开销。
七 代理模式
代理模式分为静态代理和动态代理,下面主要展示静态代理的类图结构,静态代理中代理类和被代理类都实现相同的接口。
代码解释
- 抽象主题接口(
Subject
):定义了真实主题和代理主题的公共接口,包含一个request()
方法,该方法是客户端可以调用的操作。 - 真实主题类(
RealSubject
):实现了Subject
接口,是实际要被代理的对象,request()
方法中包含了具体的业务逻辑。 - 代理类(
ProxySubject
):同样实现了Subject
接口,持有一个RealSubject
对象的引用。在request()
方法中,它可以在调用真实主题的request()
方法前后添加一些额外的操作,比如权限验证、日志记录等。 - 客户端类(
Client
):依赖于ProxySubject
类,通过代理类来间接访问真实主题的功能。
模式解释
代理模式的核心思想是通过一个代理对象来控制对另一个对象(真实对象)的访问。代理对象和真实对象实现相同的接口,这样客户端可以像使用真实对象一样使用代理对象。代理对象可以在不改变真实对象的情况下,对其功能进行增强或控制。
设计模式是软件开发中针对反复出现的问题所总结归纳出的通用解决方案,它可以帮助开发者更高效地构建软件系统,提升代码的可维护性、可扩展性和可复用性。