牛刀小试设计模式
目录
设计模式简介
什么是设计模式
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中一些不断重复出现的问题,以及该问题的解决方案。
设计模式的核心价值
1. 提高代码质量
- 可读性:使用标准化的模式,代码更容易理解
- 可维护性:结构清晰,便于修改和扩展
- 可复用性:模式化的代码更容易在不同项目中复用
2. 解决常见问题
- 解耦:降低类之间的耦合度
- 扩展:便于功能的扩展和修改
- 复用:提高代码的复用性
3. 团队协作
- 沟通:团队成员对设计模式有共同理解
- 规范:统一的代码设计规范
- 效率:减少重复思考和设计时间
设计模式的历史
时间 | 重要事件 | 影响 |
---|---|---|
1977年 | Christopher Alexander提出建筑模式概念 | 为软件设计模式奠定基础 |
1994年 | Gang of Four (GoF) 发布《设计模式》 | 正式确立23种经典设计模式 |
2002年 | Martin Fowler发布《企业应用架构模式》 | 扩展了企业级应用设计模式 |
2008年 | 微服务架构兴起 | 涌现出新的架构模式 |
2014年 | 响应式编程模式 | 适应现代异步编程需求 |
设计模式分类
按目的分类
1. 创建型模式(Creational Patterns)
目的:解决对象创建的问题
模式名称 | 英文名称 | 主要作用 | 使用频率 |
---|---|---|---|
单例模式 | Singleton | 确保一个类只有一个实例 | ⭐⭐⭐⭐⭐ |
工厂方法模式 | Factory Method | 创建对象而不指定具体类 | ⭐⭐⭐⭐ |
抽象工厂模式 | Abstract Factory | 创建相关对象族 | ⭐⭐⭐ |
建造者模式 | Builder | 分步构建复杂对象 | ⭐⭐⭐ |
原型模式 | Prototype | 通过克隆创建对象 | ⭐⭐ |
2. 结构型模式(Structural Patterns)
目的:解决类和对象的组合问题
模式名称 | 英文名称 | 主要作用 | 使用频率 |
---|---|---|---|
适配器模式 | Adapter | 让不兼容的接口协同工作 | ⭐⭐⭐⭐ |
装饰器模式 | Decorator | 动态添加功能 | ⭐⭐⭐⭐ |
代理模式 | Proxy | 为对象提供代理控制访问 | ⭐⭐⭐⭐ |
外观模式 | Facade | 为子系统提供统一接口 | ⭐⭐⭐ |
桥接模式 | Bridge | 分离抽象和实现 | ⭐⭐ |
组合模式 | Composite | 树形结构处理 | ⭐⭐ |
享元模式 | Flyweight | 共享细粒度对象 | ⭐ |
3. 行为型模式(Behavioral Patterns)
目的:解决对象间的通信和职责分配问题
模式名称 | 英文名称 | 主要作用 | 使用频率 |
---|---|---|---|
观察者模式 | Observer | 定义一对多依赖关系 | ⭐⭐⭐⭐⭐ |
策略模式 | Strategy | 定义算法族,使它们可互换 | ⭐⭐⭐⭐ |
命令模式 | Command | 将请求封装为对象 | ⭐⭐⭐⭐ |
模板方法模式 | Template Method | 定义算法骨架 | ⭐⭐⭐⭐ |
状态模式 | State | 改变对象行为 | ⭐⭐⭐ |
责任链模式 | Chain of Responsibility | 避免请求发送者和接收者耦合 | ⭐⭐⭐ |
迭代器模式 | Iterator | 顺序访问聚合对象 | ⭐⭐⭐ |
中介者模式 | Mediator | 减少对象间直接交互 | ⭐⭐ |
备忘录模式 | Memento | 保存和恢复对象状态 | ⭐⭐ |
访问者模式 | Visitor | 在不改变类结构下定义新操作 | ⭐ |
解释器模式 | Interpreter | 定义语言语法 | ⭐ |
按范围分类
1. 类模式
- 处理类与子类之间的关系
- 通过继承建立关系
- 编译时确定关系
典型模式:
- 模板方法模式
- 工厂方法模式
- 适配器模式(类适配器)
2. 对象模式
- 处理对象间的关系
- 通过组合建立关系
- 运行时确定关系
典型模式:
- 单例模式
- 观察者模式
- 策略模式
- 装饰器模式
设计模式使用场景
创建型模式使用场景
1. 单例模式
适用场景:
- 需要全局唯一实例的类
- 资源管理器(数据库连接池、线程池)
- 配置管理器
- 日志记录器
// 线程安全的单例模式
public class DatabaseConnection {
private static volatile DatabaseConnection instance;
private DatabaseConnection() {}
public static DatabaseConnection getInstance() {
if (instance == null) {
synchronized (DatabaseConnection.class) {
if (instance == null) {
instance = new DatabaseConnection();
}
}
}
return instance;
}
}
2. 工厂方法模式
适用场景:
- 创建对象时不知道具体类型
- 需要根据条件创建不同对象
- 希望扩展产品类型
// 支付方式工厂
public interface PaymentFactory {
Payment createPayment();
}
public class AlipayFactory implements PaymentFactory {
@Override
public Payment createPayment() {
return new AlipayPayment();
}
}
public class WechatPayFactory implements PaymentFactory {
@Override
public Payment createPayment() {
return new WechatPayPayment();
}
}
3. 建造者模式
适用场景:
- 构建复杂对象
- 需要分步构建
- 构建过程需要灵活配置
// 用户信息建造者
public class User {
private String name;
private String email;
private int age;
private String address;
private User(Builder builder) {
this.name = builder.name;
this.email = builder.email;
this.age = builder.age;
this.address = builder.address;
}
public static class Builder {
private String name;
private String email;
private int age;
private String address;
public Builder name(String name) {
this.name = name;
return this;
}
public Builder email(String email) {
this.email = email;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public Builder address(String address) {
this.address = address;
return this;
}
public User build() {
return new User(this);
}
}
}
结构型模式使用场景
1. 适配器模式
适用场景:
- 使用第三方库时接口不匹配
- 系统升级时保持向后兼容
- 集成不同厂商的组件
// 媒体播放器适配器
public interface MediaPlayer {
void play(String audioType, String fileName);
}
public interface AdvancedMediaPlayer {
void playVlc(String fileName);
void playMp4(String fileName);
}
public class MediaAdapter implements MediaPlayer {
AdvancedMediaPlayer advancedMusicPlayer;
public MediaAdapter(String audioType) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer = new Mp4Player();
}
}
@Override
public void play(String audioType, String fileName) {
if (audioType.equalsIgnoreCase("vlc")) {
advancedMusicPlayer.playVlc(fileName);
} else if (audioType.equalsIgnoreCase("mp4")) {
advancedMusicPlayer.playMp4(fileName);
}
}
}
2. 装饰器模式
适用场景:
- 需要动态添加功能
- 不能使用继承时
- 需要透明地扩展对象功能
// 咖啡装饰器
public abstract class Coffee {
public abstract String getDescription();
public abstract double cost();
}
public class SimpleCoffee extends Coffee {
@Override
public String getDescription() {
return "Simple coffee";
}
@Override
public double cost() {
return 1.0;
}
}
public abstract class CoffeeDecorator extends Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
public class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + ", milk";
}
@Override
public double cost() {
return coffee.cost() + 0.5;
}
}
3. 代理模式
适用场景:
- 需要控制对对象的访问
- 延迟加载
- 缓存代理
- 权限控制
// 图片代理
public interface Image {
void display();
}
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName) {
System.out.println("Loading " + fileName);
}
}
public class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
}
}
行为型模式使用场景
1. 观察者模式
适用场景:
- 一对多依赖关系
- 事件处理系统
- 模型-视图架构
- 发布-订阅系统
// 新闻发布订阅系统
public interface Observer {
void update(String news);
}
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
public class NewsAgency implements Subject {
private List<Observer> observers = new ArrayList<>();
private String news;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(news);
}
}
public void setNews(String news) {
this.news = news;
notifyObservers();
}
}
public class NewsChannel implements Observer {
private String name;
public NewsChannel(String name) {
this.name = name;
}
@Override
public void update(String news) {
System.out.println(name + " received news: " + news);
}
}
2. 策略模式
适用场景:
- 需要动态选择算法
- 算法族需要互换
- 避免使用多重条件判断
// 支付策略
public interface PaymentStrategy {
void pay(double amount);
}
public class CreditCardPayment implements PaymentStrategy {
private String cardNumber;
private String cvv;
public CreditCardPayment(String cardNumber, String cvv) {
this.cardNumber = cardNumber;
this.cvv = cvv;
}
@Override
public void pay(double amount) {
System.out.println("Paid " + amount + " using Credit Card");
}
}
public class PayPalPayment implements PaymentStrategy {
private String email;
public PayPalPayment(String email) {
this.email = email;
}
@Override
public void pay(double amount) {
System.out.println("Paid " + amount + " using PayPal");
}
}
public class PaymentContext {
private PaymentStrategy strategy;
public PaymentContext(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void executePayment(double amount) {
strategy.pay(amount);
}
}
3. 命令模式
适用场景:
- 需要撤销/重做操作
- 需要将请求排队
- 需要支持日志和事务
// 遥控器命令
public interface Command {
void execute();
void undo();
}
public class Light {
public void on() {
System.out.println("Light is on");
}
public void off() {
System.out.println("Light is off");
}
}
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
设计模式重难点分析
创建型模式重难点
1. 单例模式
重难点:
- 线程安全:多线程环境下的实例创建
- 序列化:防止反序列化创建新实例
- 反射攻击:防止通过反射创建实例
- 内存泄漏:静态实例的生命周期管理
解决方案:
// 枚举单例(推荐)
public enum Singleton {
INSTANCE;
public void doSomething() {
// 业务逻辑
}
}
// 双重检查锁定
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
2. 工厂模式
重难点:
- 简单工厂 vs 工厂方法:选择合适的工厂模式
- 抽象工厂的复杂性:管理多个产品族
- 扩展性:添加新产品时的修改成本
解决方案:
// 使用反射的通用工厂
public class GenericFactory<T> {
private Map<String, Class<? extends T>> registeredClasses = new HashMap<>();
public void registerClass(String type, Class<? extends T> clazz) {
registeredClasses.put(type, clazz);
}
public T create(String type) {
Class<? extends T> clazz = registeredClasses.get(type);
if (clazz == null) {
throw new IllegalArgumentException("Unknown type: " + type);
}
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("Failed to create instance", e);
}
}
}
结构型模式重难点
1. 适配器模式
重难点:
- 类适配器 vs 对象适配器:选择合适的实现方式
- 接口设计:如何设计合适的适配器接口
- 性能影响:适配器可能带来的性能开销
解决方案:
// 对象适配器(推荐)
public class ObjectAdapter implements Target {
private Adaptee adaptee;
public ObjectAdapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
2. 装饰器模式
重难点:
- 装饰器链:多个装饰器的组合使用
- 顺序问题:装饰器的应用顺序
- 性能考虑:装饰器链的性能影响
解决方案:
// 装饰器链管理
public class DecoratorChain {
private List<Decorator> decorators = new ArrayList<>();
public void addDecorator(Decorator decorator) {
decorators.add(decorator);
}
public Component build(Component component) {
Component result = component;
for (Decorator decorator : decorators) {
result = decorator.decorate(result);
}
return result;
}
}
行为型模式重难点
1. 观察者模式
重难点:
- 内存泄漏:观察者未正确移除
- 通知顺序:多个观察者的通知顺序
- 异常处理:观察者处理异常时的策略
解决方案:
// 安全的观察者模式
public class SafeSubject implements Subject {
private List<Observer> observers = new CopyOnWriteArrayList<>();
@Override
public void notifyObservers() {
for (Observer observer : observers) {
try {
observer.update();
} catch (Exception e) {
// 记录异常,不影响其他观察者
System.err.println("Observer failed: " + e.getMessage());
}
}
}
}
2. 策略模式
重难点:
- 策略选择:如何选择合适的策略
- 策略切换:运行时策略切换的复杂性
- 策略组合:多个策略的组合使用
解决方案:
// 策略选择器
public class StrategySelector {
private Map<String, Strategy> strategies = new HashMap<>();
public void registerStrategy(String key, Strategy strategy) {
strategies.put(key, strategy);
}
public Strategy selectStrategy(String key) {
Strategy strategy = strategies.get(key);
if (strategy == null) {
throw new IllegalArgumentException("Unknown strategy: " + key);
}
return strategy;
}
}
设计模式在实际项目中的应用
Spring框架中的设计模式
1. 单例模式
// Spring Bean默认单例
@Component
public class UserService {
// Spring容器管理单例
}
// 配置单例
@Configuration
public class AppConfig {
@Bean
@Scope("singleton")
public DataSource dataSource() {
return new HikariDataSource();
}
}
2. 工厂模式
// Spring的BeanFactory
@Configuration
public class PaymentConfig {
@Bean
public PaymentFactory paymentFactory() {
return new PaymentFactory();
}
@Bean
public PaymentService paymentService(PaymentFactory factory) {
return new PaymentService(factory);
}
}
3. 代理模式
// Spring AOP代理
@Service
public class UserService {
@Transactional
public void saveUser(User user) {
// 业务逻辑
}
@Cacheable("users")
public User findById(Long id) {
// 查询逻辑
}
}
4. 观察者模式
// Spring事件机制
@Component
public class UserEventListener {
@EventListener
public void handleUserCreated(UserCreatedEvent event) {
// 处理用户创建事件
}
@EventListener
public void handleUserUpdated(UserUpdatedEvent event) {
// 处理用户更新事件
}
}
// 发布事件
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createUser(User user) {
// 创建用户逻辑
eventPublisher.publishEvent(new UserCreatedEvent(user));
}
}
微服务架构中的设计模式
1. 服务发现模式
// 服务注册
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}
// 服务发现
@Service
public class OrderService {
@Autowired
private DiscoveryClient discoveryClient;
public List<ServiceInstance> getUserServiceInstances() {
return discoveryClient.getInstances("user-service");
}
}
2. 熔断器模式
// Hystrix熔断器
@Service
public class UserService {
@HystrixCommand(fallbackMethod = "getUserFallback")
public User getUser(Long id) {
// 调用远程服务
return userClient.getUser(id);
}
public User getUserFallback(Long id) {
return new User(id, "Default User");
}
}
3. 网关模式
// Spring Cloud Gateway
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("user-service", r -> r.path("/api/users/**")
.uri("lb://user-service"))
.route("order-service", r -> r.path("/api/orders/**")
.uri("lb://order-service"))
.build();
}
}
数据库操作中的设计模式
1. 仓储模式
// 通用仓储接口
public interface Repository<T, ID> {
T save(T entity);
Optional<T> findById(ID id);
List<T> findAll();
void deleteById(ID id);
}
// 用户仓储
@Repository
public class UserRepository implements Repository<User, Long> {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public User save(User user) {
// 保存用户逻辑
return user;
}
@Override
public Optional<User> findById(Long id) {
// 查询用户逻辑
return Optional.empty();
}
}
2. 工作单元模式
// 工作单元接口
public interface UnitOfWork {
void registerNew(Object entity);
void registerDirty(Object entity);
void registerDeleted(Object entity);
void commit();
void rollback();
}
// 工作单元实现
@Component
public class JpaUnitOfWork implements UnitOfWork {
@Autowired
private EntityManager entityManager;
private List<Object> newEntities = new ArrayList<>();
private List<Object> dirtyEntities = new ArrayList<>();
private List<Object> deletedEntities = new ArrayList<>();
@Override
public void registerNew(Object entity) {
newEntities.add(entity);
}
@Override
public void commit() {
try {
for (Object entity : newEntities) {
entityManager.persist(entity);
}
for (Object entity : dirtyEntities) {
entityManager.merge(entity);
}
for (Object entity : deletedEntities) {
entityManager.remove(entity);
}
entityManager.getTransaction().commit();
} catch (Exception e) {
entityManager.getTransaction().rollback();
throw e;
}
}
}
缓存设计中的设计模式
1. 装饰器模式
// 缓存装饰器
public class CachedUserService implements UserService {
private final UserService userService;
private final CacheManager cacheManager;
public CachedUserService(UserService userService, CacheManager cacheManager) {
this.userService = userService;
this.cacheManager = cacheManager;
}
@Override
public User findById(Long id) {
Cache cache = cacheManager.getCache("users");
User user = cache.get(id, User.class);
if (user == null) {
user = userService.findById(id);
cache.put(id, user);
}
return user;
}
}
2. 策略模式
// 缓存策略
public interface CacheStrategy {
void put(String key, Object value);
Object get(String key);
void evict(String key);
}
// LRU缓存策略
public class LRUCacheStrategy implements CacheStrategy {
private final Map<String, Object> cache = new LinkedHashMap<String, Object>(16, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry<String, Object> eldest) {
return size() > 1000;
}
};
@Override
public synchronized void put(String key, Object value) {
cache.put(key, value);
}
@Override
public synchronized Object get(String key) {
return cache.get(key);
}
}
设计模式最佳实践
1. 模式选择原则
何时使用设计模式
- 问题重复出现:相同问题多次遇到
- 代码结构复杂:需要更好的组织结构
- 团队协作:需要统一的代码规范
- 系统扩展:需要支持未来扩展
何时不使用设计模式
- 过度设计:简单问题不需要复杂模式
- 性能敏感:模式可能带来性能开销
- 团队不熟悉:团队对模式理解不够
- 项目时间紧张:没有足够时间设计
2. 模式组合使用
常见模式组合
// 工厂 + 单例 + 策略
public class PaymentProcessor {
private static final PaymentProcessor INSTANCE = new PaymentProcessor();
private final Map<String, PaymentStrategy> strategies = new HashMap<>();
private PaymentProcessor() {
// 注册策略
strategies.put("credit", new CreditCardStrategy());
strategies.put("paypal", new PayPalStrategy());
}
public static PaymentProcessor getInstance() {
return INSTANCE;
}
public void processPayment(String type, double amount) {
PaymentStrategy strategy = strategies.get(type);
if (strategy != null) {
strategy.pay(amount);
} else {
throw new IllegalArgumentException("Unknown payment type: " + type);
}
}
}
3. 反模式识别
常见反模式
- God Object:一个类承担过多职责
- Spaghetti Code:代码结构混乱
- Copy-Paste Programming:重复代码过多
- Golden Hammer:过度使用某个模式
解决方案
// 反模式:God Object
public class UserManager {
public void createUser() { /* ... */ }
public void updateUser() { /* ... */ }
public void deleteUser() { /* ... */ }
public void sendEmail() { /* ... */ }
public void logActivity() { /* ... */ }
public void generateReport() { /* ... */ }
}
// 改进:职责分离
public class UserService {
public void createUser() { /* ... */ }
public void updateUser() { /* ... */ }
public void deleteUser() { /* ... */ }
}
public class EmailService {
public void sendEmail() { /* ... */ }
}
public class LoggingService {
public void logActivity() { /* ... */ }
}
public class ReportService {
public void generateReport() { /* ... */ }
}
4. 性能考虑
模式性能影响
模式 | 性能影响 | 建议 |
---|---|---|
单例模式 | 低 | 推荐使用 |
工厂模式 | 低 | 推荐使用 |
装饰器模式 | 中 | 注意装饰器链长度 |
代理模式 | 中 | 考虑动态代理开销 |
观察者模式 | 中 | 注意观察者数量 |
策略模式 | 低 | 推荐使用 |
性能优化建议
// 对象池模式
public class ObjectPool<T> {
private final Queue<T> pool = new ConcurrentLinkedQueue<>();
private final Supplier<T> factory;
private final int maxSize;
public ObjectPool(Supplier<T> factory, int maxSize) {
this.factory = factory;
this.maxSize = maxSize;
}
public T acquire() {
T object = pool.poll();
if (object == null) {
object = factory.get();
}
return object;
}
public void release(T object) {
if (pool.size() < maxSize) {
pool.offer(object);
}
}
}
总结
设计模式的核心价值
- 提高代码质量:使代码更加清晰、可维护、可扩展
- 解决常见问题:提供经过验证的解决方案
- 促进团队协作:建立统一的代码设计规范
- 降低学习成本:新团队成员更容易理解代码
学习建议
- 循序渐进:从简单模式开始,逐步学习复杂模式
- 实践为主:通过实际项目应用模式
- 理解原理:不仅要知道如何使用,更要理解为什么
- 避免过度使用:根据实际需要选择合适的模式
未来趋势
- 函数式编程模式:适应现代编程范式
- 响应式编程模式:处理异步和流式数据
- 微服务架构模式:支持分布式系统设计
- 云原生模式:适应云计算环境
设计模式是软件工程中的重要工具,掌握它们能够显著提高代码质量和开发效率。但记住,模式是工具,不是目的,应该根据实际需要合理使用。