第五篇 设计模式的选择和应用 - 智慧选择与合理实践

简介: 第五篇 设计模式的选择和应用 - 智慧选择与合理实践

1. 如何识别和选择合适的设计模式

  1. 理解问题本质:首先,要深入理解面临的问题或需求。分析系统中的对象、它们之间的关系以及可能出现的变化点。了解哪些部分需要灵活性、扩展性或者解耦。
  2. 模式匹配:根据问题特征对照已知的设计模式,识别出可能适用的模式类型。例如,若遇到对象创建过程复杂且需要解耦,可以考虑使用工厂方法、抽象工厂或建造者模式;若需处理对象间复杂的交互逻辑,则可考虑责任链、中介者或观察者模式等。
  3. 权衡比较:对于多种可能适用的设计模式,进行对比分析,考虑每种模式带来的优缺点。如复用程度、代码可读性、维护成本、性能影响等因素。
  1. 实际场景结合:确保所选模式符合项目的具体应用场景,同时考虑到系统的未来发展变化。确保选择的设计模式能够适应业务需求的演变,而不是仅仅为了应用模式而模式化设计。

2. 设计模式的权衡和适用场景分析

在选择和应用设计模式时,必须认识到每个模式都有其适用范围和局限性:

  • 一些模式可能会增加系统的复杂性,特别是在小型项目中过度使用。
  • 有些模式可能提高代码的可读性和复用性,但可能导致运行时性能下降(如工厂方法产生的类实例增多)。
  • 有的模式如单例和全局状态可能会导致难以测试和扩展。

因此,在决定采用某个设计模式时,应综合评估该模式在当前场景下的价值,包括是否解决了特定问题、是否会带来其他潜在问题以及未来可能的需求变化。

3 设计模式在实际项目中的应用案例分享

3.1. Spring框架中的依赖注入

Spring通过实现控制反转(IoC)和依赖注入(DI),实际上采用了工厂方法、策略和代理等模式,使得组件间的耦合度降低,更易于测试和维护。

Spring框架通过依赖注入(DI)实现控制反转(IoC),在实际应用中确实采用了工厂方法、策略和代理等模式的变体。下面分别以代码片段的形式说明:

1. 工厂方法模式的体现:BeanFactory与ApplicationContext

Spring中的BeanFactory接口是IoC容器的基本实现,它扮演了抽象工厂角色,负责管理和创建各种对象(即bean)。而ApplicationContext作为BeanFactory的高级实现,更加强大且功能丰富。

// Spring BeanFactory 实现了工厂方法模式
public interface BeanFactory {
    Object getBean(String name) throws BeansException;
    // ... 其他获取bean的方法
}

// 通常我们使用 ApplicationContext 来获取 bean
public class ClassPathXmlApplicationContext implements ApplicationContext {
    public Object getBean(String name) throws BeansException {
        // ...
    }
}

2. 策略模式的体现:例如数据源配置切换

Spring允许通过Java配置或XML配置定义多个数据源,并根据运行时条件选择不同的数据源策略。

@Configuration
public class DataSourceConfig {

    @Autowired
    private Environment env;

    @Bean
    @Primary
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create()
                .url(env.getProperty("primary.datasource.url"))
                .username(env.getProperty("primary.datasource.username"))
                .password(env.getProperty("primary.datasource.password"))
                .build();
    }

    @Bean
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create()
                .url(env.getProperty("secondary.datasource.url"))
                .username(env.getProperty("secondary.datasource.username"))
                .password(env.getProperty("secondary.datasource.password"))
                .build();
    }

    // 在其他类中注入时可以按需选择数据源策略
    @Service
    public class SomeService {
    
        @Autowired
        private DataSource dataSource; // 这里注入的数据源可能是primaryDataSource也可能是secondaryDataSource
        
        // 根据业务需求决定使用哪个数据源
        // ...
    }
}

3. 代理模式的体现:AOP和动态代理

Spring通过AOP(面向切面编程)机制实现了对目标对象的代理,如事务管理、日志记录等。

@Aspect
@Component
public class TransactionalAdvice {

    @Before("execution(* com.example.service.*.*(..))")
    public void before(JoinPoint joinPoint) {
        // 开启事务的逻辑
    }

    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void afterReturning(Object result) {
        // 提交事务的逻辑
    }
    
    // 其他通知...
}

@Service
public class UserServiceImpl implements UserService {

    // 这个UserService的实例在Spring IoC容器中实际上是被代理的对象
    @Override
    public void addUser(User user) {
        // 添加用户逻辑
    }
}

在这个例子中,Spring通过生成代理对象来拦截目标方法调用,从而实现了诸如事务管理这样的横切关注点。这就是代理模式在Spring AOP中的应用。Spring既可以使用JDK动态代理,也可以使用CGLIB库进行代理实现。

3.2. 电商购物车模块

在构建购物车功能时,可以使用组合模式来表示商品项及其子项(如套装内包含多个单品),利用观察者模式实现实时总价计算,当添加或删除商品时通知观察者更新总价。

由于文本交互的限制,下面将简要说明如何使用组合模式和观察者模式来实现电商购物车模块,并给出部分伪代码以展示关键逻辑。

1. 组合模式(Composite Pattern)

首先,定义一个商品接口Product以及它的两种实现:单品SingleProduct和套装BundleProduct。套装内可以包含多个子商品项,即采用组合结构。

// 商品抽象类或接口
public abstract class Product {
    protected double price;
    
    public abstract void add(Product product);
    public abstract void remove(Product product);
    // ... 其他如获取价格、名称等方法
}

// 单品商品
public class SingleProduct extends Product {
    private String name;
    
    public SingleProduct(String name, double price) {
        this.name = name;
        this.price = price;
    }
    
    @Override
    public void add(Product product) {
        throw new UnsupportedOperationException("单个商品不能添加子商品");
    }

    @Override
    public void remove(Product product) {
        throw new UnsupportedOperationException("单个商品没有子商品可移除");
    }
    // ...
}

// 套装商品,内部维护一个产品列表
public class BundleProduct extends Product {
    private List<Product> productList = new ArrayList<>();
    
    public void add(Product product) {
        productList.add(product);
    }

    public void remove(Product product) {
        productList.remove(product);
    }

    @Override
    public double getPrice() {
        double totalPrice = 0;
        for (Product item : productList) {
            totalPrice += item.getPrice();
        }
        return totalPrice;
    }
    // ...
}

2. 观察者模式(Observer Pattern)

定义一个Cart购物车类,它持有商品集合并实现了观察者模式。当商品数量变化时,购物车总价自动更新。

import java.util.ArrayList;
import java.util.List;

// 购物车接口,同时作为观察目标(Observable)
public interface Cart extends ObserverTarget {
    void addItem(Product product);
    void removeItem(Product product);
    double getTotalPrice();
    // 注册和删除观察者的方法由ObserverTarget提供
}

// 购物车实现
public class ShoppingCart implements Cart {
    private List<Product> cartItems = new ArrayList<>();
    private List<Observer> observers = new ArrayList<>();

    @Override
    public void addItem(Product product) {
        cartItems.add(product);
        notifyObservers(); // 添加商品后通知所有观察者
    }

    @Override
    public void removeItem(Product product) {
        cartItems.remove(product);
        notifyObservers(); // 移除商品后通知所有观察者
    }

    @Override
    public double getTotalPrice() {
        double totalPrice = 0;
        for (Product item : cartItems) {
            totalPrice += item.getPrice();
        }
        return totalPrice;
    }

    // 实现ObserverTarget接口中的注册与通知方法
    @Override
    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(this); // 更新观察者(例如总价显示组件)
        }
    }
}

// 观察者接口
public interface Observer {
    void update(Cart cart);
}

// 总价显示组件作为观察者
public class TotalPriceDisplay implements Observer {
    @Override
    public void update(Cart cart) {
        double totalPrice = cart.getTotalPrice();
        // 更新UI或其他操作,显示最新的总价
    }
}

在这个例子中,当我们向购物车中添加或删除商品时,购物车会触发notifyObservers()方法通知所有的观察者(如总价显示组件),观察者通过调用update()方法来获取最新的购物车总价并进行相应更新。这样就实现了在添加或删除商品时实时计算并更新购物车总价的功能。

3.3. GUI事件处理

GUI编程中广泛使用了事件监听机制,这背后隐藏着观察者模式的应用,当用户触发按钮点击等事件时,相应的处理器会接收到通知并执行相应操作。

4. 避免设计模式的滥用和过度设计

设计模式虽好,但如果滥用或过度设计,反而会导致代码过于复杂,增加理解和维护难度。以下是一些避免滥用和过度设计的建议:

  • 只有在真正需要解决特定设计问题时才引入设计模式,不要为模式而模式。
  • 在设计初期保持简洁,随着需求迭代逐渐优化结构,适时引入设计模式以应对复用、扩展和解耦的需求。
  • 对于简单的场景,优先选择简单直观的设计方案,无需刻意追求高级设计模式。
  • 在团队协作中建立良好的设计规范,明确何时、何地以及如何恰当地使用设计模式。

总结来说,选择和应用设计模式的关键在于深入理解其原理,把握好适用的时机,并结合实际情况灵活运用,最终目的是为了提升软件的可读性、可维护性和可扩展性,而非盲目追求理论上的完美设计。

相关文章
|
1月前
|
设计模式 前端开发 JavaScript
【JavaScript 技术专栏】JavaScript 设计模式与实战应用
【4月更文挑战第30天】本文探讨JavaScript设计模式在提升开发效率和代码质量中的关键作用。涵盖单例、工厂、观察者、装饰器和策略模式,并通过实例阐述其在全局状态管理、复杂对象创建、实时数据更新、功能扩展和算法切换的应用。理解并运用这些模式能帮助开发者应对复杂项目,提升前端开发能力。
|
1天前
|
设计模式 PHP 开发者
PHP中的设计模式及其应用
在现代软件开发中,设计模式是一种被广泛采纳的方法论,能够帮助开发者解决常见的设计问题并提高代码的灵活性和可维护性。本文将深入探讨PHP中几种常用的设计模式,包括工厂模式、单例模式和观察者模式,分析它们的实现方式以及在实际项目中的应用场景,帮助读者理解和运用这些模式来优化自己的PHP代码设计。
|
16天前
|
设计模式 开发框架 算法
C++中的设计模式:基本概念与应用
C++中的设计模式:基本概念与应用
24 2
|
18天前
|
设计模式 存储 前端开发
Java的mvc设计模式在web开发中应用
Java的mvc设计模式在web开发中应用
|
28天前
|
设计模式 缓存
理解并应用设计模式在软件开发中的重要性
【5月更文挑战第20天】设计模式是软件开发中的最佳实践,用于解决常见设计问题,提高代码可读性、可维护性、可扩展性和灵活性。本文介绍了为何需要设计模式(如管理依赖、增强可重用性、设计易扩展系统)以及常见的设计模式:工厂模式(封装对象创建)、单例模式(确保类唯一实例)、观察者模式(事件驱动)和适配器模式(解决接口不兼容)。应用设计模式的关键步骤包括识别问题、选择模式、实现模式及测试优化。设计模式对于提升代码质量和降低系统风险至关重要。
|
1月前
|
设计模式 JavaScript 算法
js设计模式-策略模式与代理模式的应用
策略模式和代理模式是JavaScript常用设计模式。策略模式通过封装一系列算法,使它们可互换,让算法独立于客户端,提供灵活的选择。例如,定义不同计算策略并用Context类执行。代理模式则为对象提供代理以控制访问,常用于延迟加载或权限控制。如创建RealSubject和Proxy类,Proxy在调用RealSubject方法前可执行额外操作。这两种模式在复杂业务逻辑中发挥重要作用,根据需求选择合适模式解决问题。
|
1月前
|
设计模式 算法 Java
设计模式在Java开发中的应用
设计模式在Java开发中的应用
22 0
|
1月前
|
设计模式 存储 前端开发
18:JavaBean简介及其在表单处理与DAO设计模式中的应用-Java Web
18:JavaBean简介及其在表单处理与DAO设计模式中的应用-Java Web
35 4
|
1月前
|
设计模式 算法 搜索推荐
【PHP开发专栏】PHP设计模式解析与实践
【4月更文挑战第29天】本文介绍了设计模式在PHP开发中的应用,包括创建型(如单例、工厂模式)、结构型和行为型模式(如观察者、策略模式)。通过示例展示了如何在PHP中实现这些模式,强调了它们在提升代码可维护性和可扩展性方面的作用。设计模式是解决常见问题的最佳实践,但在使用时需避免过度设计,根据实际需求选择合适的设计模式。
|
24天前
|
设计模式 Java API
【设计模式】JAVA Design Patterns——Combinator(功能模式)
【设计模式】JAVA Design Patterns——Combinator(功能模式)