目 录CONTENT

文章目录

如何优雅地将设计模式运用到实际项目中?

在等晚風吹
2024-11-21 / 0 评论 / 0 点赞 / 7 阅读 / 0 字 / 正在检测是否收录...

如何优雅地将设计模式运用到实际项目中?

🌈 设计模式介绍

所谓 “设计模式”,是一套被反复使用和验证的方法论。从更宏观的角度看,只要能够解决实际问题并符合使用场景,设计模式既可以应用于领域驱动设计(DDD),也可以用于具体的项目开发。


🤔 常用的设计模式有哪些?

  1. 策略模式(Strategy)
  2. 工厂模式(Factory)
  3. 单例模式(Singleton)
  4. 代理模式(Proxy)
  5. 工厂方法模式(Factory Method)
  6. 观察者模式(Observer)
  7. 模板方法模式(Template Method)
  8. 适配器模式(Adapter)

设计模式应用示例

以下通过具体的案例,展示设计模式如何优雅地解决实际问题。


3.1 策略模式

示例场景

商场促销活动,根据客户购买金额提供不同折扣策略:

  • 金额 ≥ 2000:打八折(0.8)。
  • 500 ≤ 金额 < 2000:打九折(0.9)。
  • 金额 < 500:打九五折(0.95)。

通过策略模式实现不同折扣策略的逻辑。

实现步骤

  1. 定义策略接口
public interface Strategy {
    String strategy(); // 返回当前策略唯一标识
    void algorithm();  // 策略计算逻辑
}
  1. 实现策略接口
public class ConcreteStrategyA implements Strategy {
    @Override
    public String strategy() {
        return StrategySelector.STRATEGY_A.getStrategy();
    }

    @Override
    public void algorithm() {
        System.out.println("process with strategyA...");
    }
}

public class ConcreteStrategyB implements Strategy {
    @Override
    public String strategy() {
        return StrategySelector.STRATEGY_B.getStrategy();
    }

    @Override
    public void algorithm() {
        System.out.println("process with strategyB...");
    }
}
  1. 定义策略枚举
@Getter
public enum StrategySelector {
    STRATEGY_A(1, "strategyA"),
    STRATEGY_B(2, "strategyB");

    private final Integer code;
    private final String strategy;

    StrategySelector(Integer code, String strategy) {
        this.code = code;
        this.strategy = strategy;
    }
}
  1. 创建策略调度器
public class StrategyRunnerImpl implements StrategyRunner {
    private static final Map<String, Strategy> STRATEGY_MAP;

    static {
        List<Strategy> strategies = List.of(new ConcreteStrategyA(), new ConcreteStrategyB());
        STRATEGY_MAP = strategies.stream().collect(Collectors.toMap(Strategy::strategy, s -> s));
    }

    @Override
    public void execute(String strategy) {
        STRATEGY_MAP.get(strategy).algorithm();
    }
}
  1. 整合至 Spring 项目

配置类通过 Spring 容器注入 StrategyRunner

@Configuration
public class StrategyConfig {
    @Bean
    public StrategyRunner runner(List<Strategy> strategies) {
        Map<String, Strategy> strategyMap = strategies.stream()
                .collect(Collectors.toMap(Strategy::strategy, s -> s));
        return strategy -> strategyMap.get(strategy).algorithm();
    }
}
  1. 控制层调用
@RestController
@RequestMapping("/designPatterns")
public class DesignPatternController {
    @Autowired
    private StrategyRunner strategyRunner;

    @GetMapping("/algorithm")
    public void algorithm(@RequestParam("strategy") String strategy) {
        strategyRunner.execute(strategy);
    }
}

效果:
访问接口后输出:

process with strategyA...

3.2 简单工厂模式

示例场景

实现支付场景:支持支付宝、微信支付,并通过工厂模式封装不同支付逻辑。

  1. 定义支付接口
public interface IPayment {
    Boolean pay(PaymentBody paymentBody);
}
  1. 实现支付接口
public class AliPay implements IPayment {
    @Override
    public Boolean pay(PaymentBody paymentBody) {
        System.out.println("支付宝支付...");
        return true;
    }
}

public class WechatPay implements IPayment {
    @Override
    public Boolean pay(PaymentBody paymentBody) {
        System.out.println("微信支付...");
        return true;
    }
}
  1. 创建支付工厂
@Component
public class PaymentFactory {
    public static IPayment getPayStrategy(String type) {
        switch (type) {
            case "AliPay": return new AliPay();
            case "WechatPay": return new WechatPay();
            default: throw new IllegalArgumentException("不支持的支付方式");
        }
    }
}
  1. 统一入口处理支付
@Component
public class PaymentStrategyHandler {
    public static Boolean pay(PaymentBody paymentBody) {
        IPayment payment = PaymentFactory.getPayStrategy(paymentBody.getType());
        return payment.pay(paymentBody);
    }
}
  1. 控制层调用
@RestController
@RequestMapping("/designPatterns")
public class DesignPatternController {
    @PostMapping("/pay")
    public Boolean pay(@RequestBody PaymentBody paymentBody) {
        return PaymentStrategyHandler.pay(paymentBody);
    }
}

3.3 单例模式

实现懒汉式单例模式(静态内部类):

class Singleton {
    private Singleton() {}

    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

3.4 代理模式

示例场景

中介代理出租房子的案例。

UsePattern1.png

  1. 定义抽象类
public interface Subject {
    void rentHouse(); // 出租房子接口
}
  1. 实现具体角色
public class HouseOwner implements Subject {
    @Override
    public void rentHouse() {
        System.out.println("房东成功出租了房子...");
    }
}
  1. 实现代理角色
public class HouseProxy implements Subject {
    private final HouseOwner houseOwner = new HouseOwner();

    @Override
    public void rentHouse() {
        System.out.println("中介收取代理费...");
        houseOwner.rentHouse();
    }
}

3.5 工厂方法模式

  1. 定义工厂接口
public interface NetworkConfigFactoryService {
    NetworkConfigCrudService getSpecificService(String productType);
}
  1. 实现工厂类
@Service
public class NetworkConfigFactoryServiceImpl implements NetworkConfigFactoryService {
    @Override
    public NetworkConfigCrudService getSpecificService(String productType) {
        switch (productType) {
            case "A": return new AServiceImpl();
            case "B": return new BServiceImpl();
            default: throw new IllegalArgumentException("未定义的产品类型");
        }
    }
}

3.6 观察者模式

示例场景

气象站监控气象变化,通知订阅者更新天气数据。

  1. 定义主题和观察者接口
interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifyObserver();
}

interface Observer {
    void update(float temp, float humidity, float pressure);
}
  1. 实现主题类
class WeatherData implements Subject {
    private final List<Observer> observers = new ArrayList<>();
    private float temperature, humidity, pressure;

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void notifyObserver() {
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    public void setMeasurements(float temp, float humidity, float pressure) {
        this.temperature = temp;
        this.humidity = humidity;
        this.pressure = pressure;
        notifyObserver();
    }
}
  1. 实现观察者类
class CurrentConditionDisplay implements Observer {
    @Override
    public void update(float temp, float humidity, float pressure) {
        System.out.println("更新天气数据:温度=" + temp + ", 湿度=" + humidity + ", 气压=" + pressure);
    }
}

效果:
当气象站数据更新时,所有订阅者自动接收最新数据并更新显示。


设计模式的优雅之处在于抽象设计和灵活扩展。结合场景选择合适的模式,能显著提高代码的可读性和可维护性。

3.7 模板方法模式

模板方法(Template Method)是一种行为设计模式,用于创建方法框架并将某些实现步骤推迟到子类中。

模板方法定义了算法的执行步骤,允许提供可能对所有或部分子类通用的默认实现。通过一个简单的例子理解该模式:假设我们要提供一个建造房子的算法,建造步骤包括:

  • 建造地基
  • 建造支柱
  • 建造墙壁
  • 安装窗户

这些步骤的顺序不可更改。例如,在建造地基前不能安装窗户。在这种情况下,可以创建一个模板方法,它定义了执行顺序,而具体实现由子类负责。

核心思想

  • 通用步骤可在父类中实现。
  • 子类可覆盖特定步骤的实现。
  • 为防止模板方法被子类覆盖,应将其定义为 final 方法。

模板方法抽象类

模板方法模式需要一个抽象基类,定义了步骤的顺序和部分实现。

示例代码

// 抽象类 HouseTemplate
public abstract class HouseTemplate {

    /**
     * 模板方法,定义了执行步骤的顺序
     */
    public final void buildHouse() {
        buildFoundation(); // 建造地基
        buildPillars();    // 建造支柱
        buildWalls();      // 建造墙壁
        buildWindows();    // 安装窗户
        System.out.println("House is built successfully");
    }

    // 通用实现:建造地基
    private void buildFoundation() {
        System.out.println("Building foundation with cement, iron rods and sand");
    }

    // 抽象方法:由子类实现
    public abstract void buildPillars();
    public abstract void buildWalls();

    // 默认实现:安装窗户
    private void buildWindows() {
        System.out.println("Building Glass Windows");
    }
}

子类实现

木屋

public class WoodenHouse extends HouseTemplate {
    @Override
    public void buildPillars() {
        System.out.println("Building Pillars With Wood coating...");
    }

    @Override
    public void buildWalls() {
        System.out.println("Building Wooden Walls...");
    }
}

玻璃房

public class GlassHouse extends HouseTemplate {
    @Override
    public void buildPillars() {
        System.out.println("Building Pillars With Glass coating...");
    }

    @Override
    public void buildWalls() {
        System.out.println("Building Glass Walls...");
    }
}

混凝土房

public class ConcreteHouse extends HouseTemplate {
    @Override
    public void buildPillars() {
        System.out.println("Building Pillars With Concrete coating...");
    }

    @Override
    public void buildWalls() {
        System.out.println("Building Concrete Walls...");
    }
}

客户端调用

public class HousingClient {
    public static void main(String[] args) {
        HouseTemplate houseBuilder;

        houseBuilder = new WoodenHouse();
        houseBuilder.buildHouse();

        System.out.println("--------------");

        houseBuilder = new GlassHouse();
        houseBuilder.buildHouse();

        System.out.println("--------------");

        houseBuilder = new ConcreteHouse();
        houseBuilder.buildHouse();
    }
}

输出结果

Building foundation with cement, iron rods and sand
Building Pillars With Wood coating...
Building Wooden Walls...
Building Glass Windows
House is built successfully
--------------
Building foundation with cement, iron rods and sand
Building Pillars With Glass coating...
Building Glass Walls...
Building Glass Windows
House is built successfully
--------------
Building foundation with cement, iron rods and sand
Building Pillars With Concrete coating...
Building Concrete Walls...
Building Glass Windows
House is built successfully

3.8 适配器模式

适配器模式(Adapter)用于将一个接口转换成另一个客户所期望的接口,使原本不兼容的类能够一起工作。

角色分析

  • 目标接口(Target):客户期待的接口。
  • 需要适配的对象(Source/Adaptee):需要适配的原始类。
  • 适配器(Adapter):通过包装适配对象,实现目标接口。

示例:网线适配器

假设我们有一根网线(Adaptee),需要通过 USB 接口(Target)连接到电脑。我们创建一个适配器来完成这个转换。

网线(Adaptee)

public class Adaptee {
    public void request() {
        System.out.println("连接网线上网");
    }
}

目标接口(Target)

public interface NetToUsb {
    void handleRequest();
}

适配器(Adapter)

public class Adapter extends Adaptee implements NetToUsb {
    @Override
    public void handleRequest() {
        super.request();
    }
}

客户端调用

public class Computer {
    public void net(NetToUsb adapter) {
        adapter.handleRequest();
    }

    public static void main(String[] args) {
        Computer computer = new Computer();
        Adapter adapter = new Adapter();
        computer.net(adapter);
    }
}

输出结果

连接网线上网

四、总结

设计模式(Design Patterns)代表最佳实践,是资深开发人员应掌握的重要技能。它们是针对常见问题的解决方案,由大量经验总结而成。

本期内容到此结束,希望对您有所帮助!

0

评论区