3W 学习法总结结构型模式(附 Java 代码实战及开源框架应用)
结构型模式 主要关注 类与对象的组合,确保不同组件之间能够高效协作,提高系统的灵活性和可维护性。本文采用 3W 学习法(What、Why、How),深入分析 七大结构型模式(适配器、桥接、装饰器、组合、外观、享元、代理),并结合 Java 代码实战 及 开源框架中的应用,帮助你高效掌握这些模式的实战技巧。
1. 适配器模式(Adapter)
✅ What:适配器模式是什么?
适配器模式 通过 转换接口 使原本不兼容的类能够一起工作。
🤔 Why:为什么要使用适配器模式?
- 解决接口不兼容问题,让新旧代码无缝衔接。
- 复用已有代码,避免修改原始代码。
🚀 How:如何实现适配器模式?(Java 代码实战)
// 目标接口
interface Target {
void request();
}
// 需要适配的类
class Adaptee {
void specificRequest() {
System.out.println("Adaptee 特定请求");
}
}
// 适配器
class Adapter implements Target {
private Adaptee adaptee = new Adaptee();
public void request() {
adaptee.specificRequest();
}
}
// 客户端调用
public class AdapterDemo {
public static void main(String[] args) {
Target target = new Adapter();
target.request(); // 输出: Adaptee 特定请求
}
}
📌 在开源框架中的应用:
- Spring
HandlerAdapter
:适配不同类型的 Controller(如RequestMappingHandlerAdapter
)。 java.io.InputStreamReader
:将InputStream
适配为Reader
。
2. 桥接模式(Bridge)
✅ What:桥接模式是什么?
桥接模式 通过 分离抽象部分和实现部分,让它们可以独立变化。
🤔 Why:为什么要使用桥接模式?
- 降低耦合:抽象和实现独立演化,不受对方影响。
- 增强扩展性:适用于 多个维度变化 的场景。
🚀 How:如何实现桥接模式?(Java 代码实战)
// 实现接口
interface Implementor {
void operationImpl();
}
// 具体实现A
class ConcreteImplementorA implements Implementor {
public void operationImpl() {
System.out.println("具体实现A的操作");
}
}
// 抽象类
abstract class Abstraction {
protected Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
abstract void operation();
}
// 具体抽象类
class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
public void operation() {
implementor.operationImpl();
}
}
// 客户端调用
public class BridgeDemo {
public static void main(String[] args) {
Implementor impl = new ConcreteImplementorA();
Abstraction abstraction = new RefinedAbstraction(impl);
abstraction.operation(); // 输出: 具体实现A的操作
}
}
📌 在开源框架中的应用:
- JDBC 驱动:
java.sql.DriverManager
通过桥接不同数据库的驱动。 - Slf4j + Logback/Log4j:日志框架使用桥接模式适配不同日志实现。
3. 装饰器模式(Decorator)
✅ What:装饰器模式是什么?
装饰器模式 通过 动态添加新功能,而不修改原有对象。
🤔 Why:为什么要使用装饰器模式?
- 符合开闭原则:可扩展对象功能,避免修改原始代码。
- 支持功能叠加:适用于 多个额外行为 组合的场景。
🚀 How:如何实现装饰器模式?(Java 代码实战)
// 抽象组件
interface Component {
void operation();
}
// 具体组件
class ConcreteComponent implements Component {
public void operation() {
System.out.println("基本功能");
}
}
// 装饰器
abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
public void operation() {
component.operation();
}
}
// 具体装饰器A
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
public void operation() {
super.operation();
System.out.println("附加功能A");
}
}
// 客户端调用
public class DecoratorDemo {
public static void main(String[] args) {
Component component = new ConcreteDecoratorA(new ConcreteComponent());
component.operation();
// 输出:
// 基本功能
// 附加功能A
}
}
📌 在开源框架中的应用:
- Spring
BeanPostProcessor
:可动态增强 Bean 的功能。 BufferedInputStream
:装饰InputStream
,提供缓冲能力。
4. 组合模式(Composite)
✅ What:组合模式是什么?
组合模式 允许 树形结构的对象 统一处理。
🤔 Why:为什么要使用组合模式?
- 统一对象处理方式:无论是单个对象还是组合对象,均可一致调用。
- 适用于层级结构:如 文件系统、组织架构 等。
🚀 How:如何实现组合模式?(Java 代码实战)
// 抽象组件
interface Component {
void operation();
}
// 叶子节点
class Leaf implements Component {
public void operation() {
System.out.println("执行叶子节点操作");
}
}
// 组合节点
class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void operation() {
for (Component child : children) {
child.operation();
}
}
}
// 客户端调用
public class CompositeDemo {
public static void main(String[] args) {
Composite root = new Composite();
root.add(new Leaf());
root.add(new Leaf());
Composite branch = new Composite();
branch.add(new Leaf());
root.add(branch);
root.operation();
}
}
📌 在开源框架中的应用:
- Spring Security:权限规则采用组合模式组织权限节点。
- GUI 组件:Swing 的
JComponent
使用组合模式。
确实,结构型模式共有 7 种,前面只介绍了 4 种,缺少了 外观模式(Facade)、享元模式(Flyweight)、代理模式(Proxy)。下面继续补充它们的 3W 学习法解析、Java 实战代码及在开源框架中的应用。
5. 外观模式(Facade)
✅ What:外观模式是什么?
外观模式(Facade) 通过 提供一个统一的接口,简化子系统的复杂操作,降低系统耦合性。
🤔 Why:为什么要使用外观模式?
- 降低复杂性,隐藏子系统细节,使调用者只需与一个简单接口交互。
- 解耦代码,避免高层代码直接依赖多个复杂子系统。
🚀 How:如何实现外观模式?(Java 代码实战)
// 子系统A
class SubsystemA {
void operationA() {
System.out.println("子系统 A 操作");
}
}
// 子系统B
class SubsystemB {
void operationB() {
System.out.println("子系统 B 操作");
}
}
// 外观类(Facade)
class Facade {
private SubsystemA subsystemA = new SubsystemA();
private SubsystemB subsystemB = new SubsystemB();
void operation() {
subsystemA.operationA();
subsystemB.operationB();
}
}
// 客户端调用
public class FacadeDemo {
public static void main(String[] args) {
Facade facade = new Facade();
facade.operation();
// 输出:
// 子系统 A 操作
// 子系统 B 操作
}
}
📌 在开源框架中的应用:
- Spring
JdbcTemplate
:封装了数据库操作,简化 JDBC 使用。 HttpClient
:简化底层 HTTP 请求的复杂性。
6. 享元模式(Flyweight)
✅ What:享元模式是什么?
享元模式(Flyweight) 通过 共享对象 来减少内存占用,提高性能。
🤔 Why:为什么要使用享元模式?
- 减少内存开销,适用于 大量相似对象 场景。
- 提升系统性能,避免重复创建对象。
🚀 How:如何实现享元模式?(Java 代码实战)
import java.util.HashMap;
import java.util.Map;
// 享元接口
interface Flyweight {
void operation(String extrinsicState);
}
// 具体享元
class ConcreteFlyweight implements Flyweight {
private final String intrinsicState;
ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
public void operation(String extrinsicState) {
System.out.println("享元对象:" + intrinsicState + ",外部状态:" + extrinsicState);
}
}
// 享元工厂
class FlyweightFactory {
private static final Map<String, Flyweight> pool = new HashMap<>();
static Flyweight getFlyweight(String key) {
if (!pool.containsKey(key)) {
pool.put(key, new ConcreteFlyweight(key));
}
return pool.get(key);
}
}
// 客户端调用
public class FlyweightDemo {
public static void main(String[] args) {
Flyweight fw1 = FlyweightFactory.getFlyweight("A");
Flyweight fw2 = FlyweightFactory.getFlyweight("A");
Flyweight fw3 = FlyweightFactory.getFlyweight("B");
fw1.operation("X");
fw2.operation("Y");
fw3.operation("Z");
System.out.println(fw1 == fw2); // 输出: true(共享同一个对象)
}
}
📌 在开源框架中的应用:
Integer.valueOf(int)
:JDK 享元模式,缓存-128 ~ 127
的 Integer 对象。- 线程池(Thread Pool):复用线程对象,减少资源消耗。
7. 代理模式(Proxy)
✅ What:代理模式是什么?
代理模式(Proxy) 通过 控制访问目标对象,增加额外行为(如权限控制、懒加载、缓存等)。
🤔 Why:为什么要使用代理模式?
- 增强功能(如日志、事务、权限)。
- 控制对象访问(如远程代理、虚拟代理)。
🚀 How:如何实现代理模式?(Java 代码实战)
静态代理
// 接口
interface Service {
void operation();
}
// 真实对象
class RealService implements Service {
public void operation() {
System.out.println("真实业务逻辑");
}
}
// 代理类
class ProxyService implements Service {
private RealService realService = new RealService();
public void operation() {
System.out.println("前置增强逻辑");
realService.operation();
System.out.println("后置增强逻辑");
}
}
// 客户端调用
public class StaticProxyDemo {
public static void main(String[] args) {
Service service = new ProxyService();
service.operation();
// 输出:
// 前置增强逻辑
// 真实业务逻辑
// 后置增强逻辑
}
}
动态代理(JDK 动态代理)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 动态代理处理器
class DynamicProxyHandler implements InvocationHandler {
private Object target;
DynamicProxyHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置增强逻辑");
Object result = method.invoke(target, args);
System.out.println("后置增强逻辑");
return result;
}
}
// 客户端调用
public class DynamicProxyDemo {
public static void main(String[] args) {
Service realService = new RealService();
Service proxy = (Service) Proxy.newProxyInstance(
realService.getClass().getClassLoader(),
realService.getClass().getInterfaces(),
new DynamicProxyHandler(realService)
);
proxy.operation();
// 输出:
// 前置增强逻辑
// 真实业务逻辑
// 后置增强逻辑
}
}
📌 在开源框架中的应用:
- Spring AOP:代理模式增强 Bean 功能,如事务、日志、权限控制。
- MyBatis Mapper:动态代理生成 SQL 查询接口的实现类。
总结
设计模式 | 主要作用 | 适用场景 |
---|---|---|
适配器模式 | 让不兼容的接口协同工作 | HandlerAdapter 、InputStreamReader |
桥接模式 | 分离抽象和实现,解耦 | JDBC 驱动、日志框架 |
装饰器模式 | 动态增强对象功能 | BufferedInputStream 、BeanPostProcessor |
组合模式 | 统一树形结构处理 | Spring Security 权限管理、GUI 组件 |
外观模式 | 简化系统调用 | JdbcTemplate 、HttpClient |
享元模式 | 共享对象减少内存消耗 | Integer.valueOf(int) 、线程池 |
代理模式 | 控制访问目标对象,增强功能 | AOP、MyBatis 动态代理 |
掌握这 7 大结构型模式,让你的代码 更清晰、可扩展、性能更优!🚀