概念实践极速入门 - 常用的设计模式 - 简单生活例子

发布于:2025-04-17 ⋅ 阅读:(22) ⋅ 点赞:(0)

概念实践极速入门 - 常用的设计模式 - 简单生活例子

SOLID 五大设计原则的首字母缩写

       单一职责原则 和 开闭原则 就省略啦, 这两个概念很简单, 为了写而写反而容易误导人~* 鼓励大家字面理解

// 哎呀还是解释吧  
单一(S): 单干一件事; 开闭(O): 拓展开放, 修改关闭!

里氏替换原则(L)

  • 仅仅发生在 继承 体系中

    • 子类不能影响父类独有行为

      • :对象构建自由与必要顺序规范鸵鸟不能飞但是继承到了鸟具有了飞的行为

        • 错误示范

          :对象构建自由与必要顺序规范重写飞的方法改成 -> ‘跑’

          不能重写父类稳定的行为

接口隔离原则(I)

  • 方式一
    对象构建自由与必要顺序规范承担非自身职责的行为 抽象为接口, 选择性依赖
  • 方式二
    对象构建自由与必要顺序规范接口默认行为空实现

依赖倒置原则(D)

  • 高层模块不应该依赖低层模块
    • 高层模块

      :业务层, 应该依赖的实现是抽象

      • 高层模块另一种解释

        :被调用方

迪米特原则(最少知识原则)- 拓展

  • 核心
    :只与直接朋友对话,减少模块耦合
  • 场景
    :订单服务不应直接调用库存DAO
// 错误示范:用户直接查货车司机信息
class User {
    void trackDelivery(Order order) {
        // 用户竟然能拿到货车司机电话!过度暴露细节
        System.out.println("货车司机电话:" + order.getTruck().getDriver().getPhone());
    }
}

// 正确做法:用户只能问订单物流状态
class User {
    void trackDelivery(Order order) {
        // 用户只需和订单对话
        System.out.println("物流状态:" + order.getDeliveryStatus()); 
    }
}

// 订单类封装物流细节
class Order {
    private Delivery delivery;
    
    String getDeliveryStatus() {
        // 内部处理复杂查询:订单→货车→司机→位置
        return "司机" + delivery.getDriverName() 
             + "正在" + delivery.getCurrentLocation();
    }
}

合成复用原则 - 拓展

  • 核心
    :优先用组合,其次继承
  • 反例
    :通过继承扩展日志功能(导致类爆炸)
// 错误示范:继承实现加料
class Americano {}
class AmericanoWithSugar extends Americano {} // 类爆炸开始
class AmericanoWithMilk extends Americano {} 
class AmericanoWithSugarAndMilk extends Americano {} // 已经失控...

// 正确示范:组合调料(合成复用)
class Coffee {
    private List<String> toppings = new ArrayList<>(); // 组合容器
    
    // 动态加料
    public void addTopping(String topping) {
        toppings.add(topping);
    }

    public void show() {
        System.out.println("咖啡加料:" + String.join("+", toppings));
    }
}

// 使用
Coffee coffee = new Coffee();
coffee.addTopping("糖");
coffee.addTopping("奶油");
coffee.show(); // 输出:咖啡加料:糖+奶油


设计模式 - 场景 与 极简摘要



一、工厂模式:创建订单

概念

:抽象共同依赖实现,通过子类决定最终逻辑

// 抽象产品接口
public interface Order {
     void create();
}

// 具体产品:普通订单
public class NormalOrder implements Order {
     @Override
     public void create() { System.out.println("创建普通订单"); }
}

// 具体产品:VIP订单
public class VipOrder implements Order {
     @Override
     public void create() { System.out.println("创建 VIP 订单"); }
}

// 工厂类:根据类型返回订单对象
public class OrderFactory {
     public Order createOrder(String type) {
          if ("vip".equals(type)) return new VipOrder();
          else return new NormalOrder();
     }
}

// 使用
Order order = new OrderFactory().createOrder("vip");
order.create();

模式作用

  • 隐藏订单具体类的创建逻辑,调用方只需传递类型参数。
  • 新增订单类型时(如团购订单),无需修改调用方代码。

二、单例模式:全局日志工具

概念
:资源独占

细节
:全局唯一

public class Logger {
     private static Logger instance;

     // 私有构造方法
     private Logger() {}

     // 双重非空检查 + 锁 保证线程安全
     public static Logger getInstance() {
          if (instance == null) {
               synchronized (Logger.class) {
                    if (instance == null) {
                         instance = new Logger();
                    }
               }
          }
          return instance;
     }

     public void log(String message) {
          System.out.println("[LOG] " + message);
     }
}

// 使用
Logger.getInstance().log("订单创建成功");

模式作用
:确保整个系统共享同一个日志实例,避免重复创建文件句柄或网络连接。


三、建造者模式:构建复杂订单对象

概念
:对象构建自由 与 必要顺序规则

public class OrderDetail {
     private String orderId; // 必要参数
     private String userId;
     private List<String> items;

     // 私有构造器,只能通过 Builder 创建
     private OrderDetail(Builder builder) {
          this.orderId = builder.orderId;
          this.userId = builder.userId;
          this.items = builder.items;
     }

     // 建造者内部类
     public static class Builder {
          private String orderId;
          private String userId;
          private List<String> items = new ArrayList<>();

          public Builder orderId(String orderId) {
               this.orderId = orderId; 
               return this;
          }        

          public Builder userId(String userId) { /* ... */ }

          public Builder addItem(String item) { /* ... */ }

          public OrderDetail build() {
               // 通过异常强制限制
               if (orderId == null) throw new IllegalArgumentException("orderId必填"); 
               return new OrderDetail(this);
          }
     }
}

// 使用
OrderDetail order = new OrderDetail.Builder()
     .orderId("123") // 这下不得不填了	总结: 选填和必填的结合
     .userId("user1")
     .addItem("手机")
     .addItem("耳机")
     .build();

模式作用

  • 解决多参数构造的混乱(尤其是可选参数),强制必要参数填写。
  • 链式调用更直观(对比含 5 个参数的构造方法)。

四、代理模式:支付前的权限校验

概念
:控制访问,代替直接访问

细节
:代理与被代理实现同一接口

// 抽象支付接口
public interface Payment {
     void pay(int amount);
}

// 具体支付类
public class Alipay implements Payment {
     @Override
     public void pay(int amount) {
          System.out.println("支付宝支付:" + amount + "元");
     }
}

// 代理类:添加权限校验
public class PaymentProxy implements Payment {
     private Payment realPayment;

     public PaymentProxy(Payment realPayment) {
          this.realPayment = realPayment;
     }

     @Override
     public void pay(int amount) {
          if (checkPermission()) {
               realPayment.pay(amount);
          } else {
               System.out.println("无权支付");
          }
     }

     private boolean checkPermission() {
          // 模拟权限检查
          return true;
     }
}

// 使用
Payment payment = new PaymentProxy(new Alipay());
payment.pay(100);

模式作用

  • 不修改 Alipay 源码的情况下,增加权限校验逻辑。
  • 符合 开闭原则(对扩展开放,对修改关闭)。

五、观察者模式:吃瓜群众

概念
:具有实时报告的行为监控
细节
:双方在打架, 吃瓜人就是观察者, 当打出什么来了(状态变更), 就去报警;
:第二个例子就是订阅,当有什么活动了,就通知

// 主题接口
interface FightSubject {
     void addObserver(Onlooker o);
     void notifyObservers(String msg);
}

// 具体打架事件
class Fight implements FightSubject {
     private List<Onlooker> people = new ArrayList<>();

     public void fightHappen(String result) {
          System.out.println("打架结果: " + result);
          notifyObservers(result);
     }

     @Override
     public void addObserver(Onlooker o) { people.add(o); }

     @Override
     public void notifyObservers(String msg) {
          people.forEach(o -> o.update(msg));
     }
}

// 观察者
class Onlooker {
     public void update(String msg) {
          if (msg.contains("倒地")) {
               System.out.println("吃瓜群众: 报警!有人受伤");
          }
     }
}

// 使用
Fight fight = new Fight();
fight.addObserver(new Onlooker());
fight.fightHappen("张三把李四打倒在地");

模式作用

  • 解耦 打架模块 和 报警模块(支付成功后不需要直接调用库存、用户服务的方法)。
  • 新增吃瓜群众时,无需修改打架代码。

六、适配器模式:兼容老插座

// 旧欧洲充电器(已有,圆头)
class EuropeanCharger {
     void roundPlug() { 
          System.out.println("⚡欧洲圆头充电中"); 
     }
}

// 美国插座标准(目标接口,方头)
interface USSocket {
     void squarePlug();
}

// 适配器:让欧洲充电器插入美国插座
class ChargerAdapter implements USSocket {
     private EuropeanCharger charger;

     public ChargerAdapter(EuropeanCharger charger) {
          this.charger = charger;
     }

     @Override
     public void squarePlug() {
          System.out.print("[适配器转换圆头→方头] ");
          charger.roundPlug(); // 实际调用旧接口
     }
}

// 使用
EuropeanCharger euroCharger = new EuropeanCharger();
USSocket adapter = new ChargerAdapter(euroCharger);
adapter.squarePlug(); // 输出: [适配器转换圆头→方头] ⚡欧洲圆头充电中

模式作用
:让旧插座无需修改即可接入新插座,解决兼容性问题。


七、装饰器模式:咖啡 与 加糖加奶

// 基础咖啡接口
interface Coffee {
     double cost();
     String desc();
}

// 具体组件:黑咖啡
class BlackCoffee implements Coffee {
     public double cost() { return 10.0; }
     public String desc() { return "黑咖啡"; }
}

// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
     protected Coffee decoratedCoffee;

     public CoffeeDecorator(Coffee coffee) {
          this.decoratedCoffee = coffee;
     }
}

// 具体装饰器:加糖
class SugarDecorator extends CoffeeDecorator {
     public SugarDecorator(Coffee coffee) {
          super(coffee);
     }

     public double cost() {
          return decoratedCoffee.cost() + 2.0; // 加糖多2元
     }

     public String desc() {
          return decoratedCoffee.desc() + "+糖";
     }
}

// 具体装饰器:加奶
class MilkDecorator extends CoffeeDecorator {
     public MilkDecorator(Coffee coffee) {
          super(coffee);
     }

     public double cost() {
          return decoratedCoffee.cost() + 5.0; // 加奶多5元
     }

     public String desc() {
          return decoratedCoffee.desc() + "+奶";
     }
}

// 使用
Coffee coffee = new BlackCoffee();
coffee = new SugarDecorator(coffee); // 加糖
coffee = new MilkDecorator(coffee);   // 再加奶

System.out.println(coffee.desc() + ",价格:" + coffee.cost());
// 输出:黑咖啡+糖+奶,价格:17.0

模式作用

  • 动态增加新功能,无需修改 黑咖啡 原始代码。

八、门面模式:一键影院模式

概念
:封装和协调统一访问的入口

// 子系统1:电灯
class Light {
     void on() { System.out.println("打开电灯"); }
}

// 子系统2:空调
class AirConditioner {
     void set25℃() { System.out.println("空调设置25℃"); }
}

// 子系统3:投影仪
class Projector {
     void down() { System.out.println("降下投影幕布"); }
}

// 门面:一键启动家庭影院模式
class HomeTheaterFacade {
     private Light light = new Light();
     private AirConditioner ac = new AirConditioner();
     private Projector projector = new Projector();

     void movieMode() {
          light.on();         // 先开灯避免磕碰
          ac.set25℃();        // 设置舒适温度
          projector.down();   // 最后降幕布
          System.out.println("➤ 影院模式就绪");
     }
}

// 使用
HomeTheaterFacade facade = new HomeTheaterFacade();
facade.movieMode(); 
// 输出:
// 打开电灯
// 空调设置25℃
// 降下投影幕布
// ➤ 影院模式就绪

模式作用

  • 调用方只需和 HomeTheaterFacade 交互,无需了解 空调 投影仪 的细节。

九、策略模式:不如停路边

概念
:算法独立于客户端使用而变化

// 策略接口:停车计费规则
interface ParkingFeeStrategy {
     double calculateFee(int hours);
}

// 具体策略1:商场普通计费(首小时5元,后续每小时3元)
class MallStrategy implements ParkingFeeStrategy {
     public double calculateFee(int hours) {
          return 5 + Math.max(0, hours - 1) * 3;
     }
}

// 具体策略2:医院惠民计费(每天上限15元)
class HospitalStrategy implements ParkingFeeStrategy {
     public double calculateFee(int hours) {
          int days = hours / 24;
          int remainder = hours % 24;
          return days * 15 + Math.min(remainder * 2, 15); // 每小时2元
     }
}

// 上下文:停车计费器
class ParkingFeeCalculator {
     private ParkingFeeStrategy strategy;

     // 初始化策略
     public ParkingFeeCalculator(ParkingFeeStrategy strategy) {
          this.strategy = strategy;
     }

     // 提供改变策略的 setter 方法
     public void setStrategy(ParkingFeeStrategy strategy) {
          this.strategy = strategy;
     }

     public void printFee(int hours) {
          System.out.println("停车" + hours + "小时,费用:" + strategy.calculateFee(hours) + "元");
     }
}

// 使用
ParkingFeeCalculator calculator = new ParkingFeeCalculator(new MallStrategy());
calculator.printFee(5);  // 输出:停车5小时,费用:17.0元

calculator.setStrategy(new HospitalStrategy());
calculator.printFee(30); // 输出:停车30小时,费用:15 * 1 + 15=30元

模式作用

  • 通过 算法类 ParkingFeeCalculator 指定具体实现策略,避免 if-else 硬编码

十、模板方法模式:定义订单处理流程

概念
:在父类定义必须算法骨架,允许子类重写特定步骤而不改变整体结构

// 抽象模板类
public abstract class OrderProcessor {
     // 模板方法(final防止子类覆盖流程)
     public final void processOrder() {
          validate();
          calculateTotal();
          saveToDatabase();
          notifyUser();
     }

     protected abstract void calculateTotal();

     protected void validate() {
          System.out.println("通用校验:订单ID非空");
     }

     protected void saveToDatabase() {
          System.out.println("保存订单到数据库");
     }

     protected void notifyUser() {
          System.out.println("发送短信通知用户");
     }
}

// 具体实现:VIP订单处理
public class VipOrderProcessor extends OrderProcessor {
     @Override
     protected void calculateTotal() {
          System.out.println("VIP订单计算:原价9折");
     }
}

// 使用
OrderProcessor processor = new VipOrderProcessor();
processor.processOrder();

模式作用

  • 固定订单处理流程(校验 → 计算 → 保存 → 通知),子类只实现差异部分(如计算逻辑)。

11. 责任链模式:审批流程

概念
:解耦请求发送者和接收者,使多个对象都有机会处理请求,形成链式处理(不等于链式编程)

// 抽象处理器:请假审批人
abstract class LeaveHandler {
     protected LeaveHandler next;
     void setNext(LeaveHandler next) { this.next = next; }
     abstract void handleRequest(int days);
}

// 具体处理器:组长(处理≤3天)
class GroupLeader extends LeaveHandler {
     void handleRequest(int days) {
          if (days <= 3) {
               System.out.println("组长批准" + days + "天假");
          } else if (next != null) {
               next.handleRequest(days); // 转交上级
          }
     }
}

// 具体处理器:经理(处理≤7天)
class Manager extends LeaveHandler {
     void handleRequest(int days) {
          if (days <= 7) {
               System.out.println("经理批准" + days + "天假");
          } else if (next != null) {
               next.handleRequest(days); // 转交上级
          }
     }
}

// 具体处理器:总监(处理任何天数)
class Director extends LeaveHandler {
     void handleRequest(int days) {
          System.out.println("总监特批" + days + "天假");
     }
}

// 使用
LeaveHandler leader = new GroupLeader();
LeaveHandler manager = new Manager();
LeaveHandler director = new Director();

leader.setNext(manager);  // 组长→经理
manager.setNext(director);// 经理→总监,(递进式处理)

leader.handleRequest(2);  // 组长批准2天假
leader.handleRequest(5);  // 组长→经理批准5天假
leader.handleRequest(15); // 组长→经理→总监特批15天假

模式作用

  • 解耦风控校验步骤,动态调整校验顺序或增删校验规则。

总结

一、分类 与 核心

1、创建型模式

模式 核心价值 典型场景
工厂模式 隐藏对象创建细节,实现类型解耦 多类型订单创建
单例模式 全局资源统一访问,避免重复实例化 日志工具、配置管理器
建造者模式 分离复杂对象的构建与表示,强制必要参数 含多可选参数的订单对象构建

2、结构型模式

模式 核心价值 典型场景
代理模式 控制访问扩展功能,符合开闭原则 支付权限校验、缓存代理
适配器模式 解决接口不兼容问题 新旧系统对接(插座转换案例)
装饰器模式 动态添加功能,避免继承导致的类爆炸 咖啡加料、日志功能增强
门面模式 简化复杂子系统调用,提供统一入口 一键影院模式集成多个设备

3、行为型模式

模式 核心价值 典型场景
观察者模式 解耦事件发布与订阅,实现松耦合通信 订单状态变更通知
策略模式 算法独立演化,支持运行时切换 多场景停车计费策略
责任链模式 动态组合处理流程,避免硬编码条件判断 多级审批/风控校验链
模板方法模式 固化流程框架,允许子类定制具体步骤 标准化订单处理流程

二、设计原则映射

1、SOLID原则实践

  • 依赖倒置:高层模块通过抽象接口调用低层实现(如订单服务依赖库存接口而非具体DAO)
  • 里氏替换:子类继承不破坏父类核心逻辑(如VIP订单处理器保持标准流程)
  • 接口隔离:按功能拆分细粒度接口(如支付接口与回调接口分离)
  • 合成复用:优先使用组合关系(装饰器模式优于多层继承)

2、其他原则

  • 开闭原则:策略模式新增算法不修改原有代码
  • 迪米特法则:订单服务通过中间层调用库存服务,避免直接操作DAO
  • 高内聚低耦合:门面模式封装子系统交互,观察者模式解耦事件处理

三、模式选型指南

1、创建场景

  • 简单对象创建 → 工厂模式
  • 含复杂构造过程 → 建造者模式
  • 全局唯一实例 → 单例模式

2、结构扩展

  • 接口转换 → 适配器模式
  • 功能动态叠加 → 装饰器模式
  • 简化复杂调用 → 门面模式
  • 访问控制 → 代理模式

3、行为管理

  • 事件驱动 → 观察者模式
  • 算法切换 → 策略模式
  • 流程审批 → 责任链模式
  • 标准化流程 → 模板方法模式

建议

  1. 识别:将易变部分抽象为策略/责任链,例
    • 支付方式、校验规则
  2. 警惕过度:简单场景直接new对象,复杂场景再考虑引入设计模式
  3. 优先组合:装饰器模式替代多层继承,保持系统弹性
  4. 遵循最少知识:模块间通过接口通信(例订单服务调用库存Service而非直接操作DAO)

end…

在这里插入图片描述

如果这篇文章帮到你, 帮忙点个关注呗, 不想那那那点赞或收藏也行鸭 (。•̀ᴗ-)✧ ~
在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述
                                                                                                                                   '(இ﹏இ`。)


网站公告

今日签到

点亮在社区的每一天
去签到