深入浅出设计模式区别

122 阅读4分钟

深入浅出设计模式区别

一、设计模式是什么?——编程界的"武功秘籍"

想象你是一名武林高手,设计模式就是你掌握的武功招式:

  • 单例模式:独门绝技,天下无双
  • 工厂模式:批量生产暗器的作坊
  • 观察者模式:千里传音之术

但有些招式看起来很像,今天我们就来拆解这些"形似神不似"的设计模式。

二、容易混淆的"双胞胎"模式

1. 工厂三兄弟:小卖部 vs 专卖店 vs 超市

简单工厂(小卖部)
// 啥都能造的小卖部
public class WeaponStore {
    public Weapon sellWeapon(String type) {
        switch(type) {
            case "sword": return new Sword();
            case "gun": return new Gun();
            default: throw new IllegalArgumentException();
        }
    }
}

特点:一个方法搞定所有产品,新增产品要修改代码

工厂方法(专卖店)
// 武器专卖店接口
public interface WeaponShop {
    Weapon sellWeapon();
}

// 剑专卖店
public class SwordShop implements WeaponShop {
    public Weapon sellWeapon() { return new Sword(); }
}

// 枪专卖店
public class GunShop implements WeaponShop {
    public Weapon sellWeapon() { return new Gun(); }
}

特点:一类产品一个工厂,扩展方便但类会增多

抽象工厂(武器超市)
// 能买全套装备的超市
public interface Armory {
    Weapon sellWeapon();
    Armor sellArmor();
}

// 现代武器超市
public class ModernArmory implements Armory {
    public Weapon sellWeapon() { return new Gun(); }
    public Armor sellArmor() { return new BulletproofVest(); }
}

// 冷兵器超市
public class MedievalArmory implements Armory {
    public Weapon sellWeapon() { return new Sword(); }
    public Armor sellArmor() { return new PlateArmor(); }
}

特点:生产成套产品,适合产品族场景

总结

  • 要简单:小卖部(简单工厂)
  • 要扩展:专卖店(工厂方法)
  • 要套装:超市(抽象工厂)

2. 观察者 vs 发布订阅:班主任通知 vs 校园广播

观察者模式(班主任直接通知)
// 班主任(被观察者)
public class Teacher extends Observable {
    void announce(String msg) {
        setChanged();
        notifyObservers(msg); // 直接通知学生
    }
}

// 学生(观察者)
public class Student implements Observer {
    void update(Observable o, Object msg) {
        System.out.println("收到通知:" + msg);
    }
}

特点:老师和学生直接联系

发布订阅模式(校园广播站)
// 广播站(中介)
public class RadioStation {
    private Map<String, List<Listener>> channels = new HashMap<>();
    
    void subscribe(String channel, Listener listener) {
        channels.computeIfAbsent(channel, k -> new ArrayList<>()).add(listener);
    }
    
    void publish(String channel, String msg) {
        channels.getOrDefault(channel, Collections.emptyList())
               .forEach(listener -> listener.onMessage(msg));
    }
}

// 学生只需要监听感兴趣频道
radio.subscribe("放学通知", msg -> System.out.println(msg));

特点:通过广播站中转,双方不知道对方存在

区别

  • 观察者:直接通信,耦合度高
  • 发布订阅:通过中介,完全解耦

3. 策略 vs 状态:主动换刀 vs 自动变形

策略模式(主动切换武器)
// 游戏角色
public class Character {
    private Weapon weapon; // 当前武器策略
    
    void changeWeapon(Weapon newWeapon) {
        this.weapon = newWeapon; // 主动更换
    }
    
    void attack() {
        weapon.attack(); // 使用当前武器攻击
    }
}

// 使用
character.changeWeapon(new Sword());
character.attack();

特点:外部主动设置策略

状态模式(自动状态转换)
// 自动售货机
public class VendingMachine {
    private State state = new IdleState();
    
    // 状态自动转换
    void insertCoin() {
        state.insertCoin(this);
    }
    
    void changeState(State newState) {
        this.state = newState;
    }
}

// 空闲状态
public class IdleState implements State {
    void insertCoin(VendingMachine vm) {
        System.out.println("投币成功");
        vm.changeState(new HasCoinState()); // 自动切换状态
    }
}

特点:状态对象控制转换逻辑

关键区别

  • 策略模式:客户端主动选择算法
  • 状态模式:状态对象自动管理转换

4. 装饰者 vs 代理:套娃增强 vs 门面控制

装饰者模式(给武器附魔)
// 基础武器
public interface Weapon {
    void attack();
}

// 火焰附魔
public class FireEnchantment implements Weapon {
    private Weapon decoratedWeapon;
    
    public FireEnchantment(Weapon weapon) {
        this.decoratedWeapon = weapon;
    }
    
    public void attack() {
        decoratedWeapon.attack();
        System.out.println("附带火焰伤害!");
    }
}

// 使用
Weapon sword = new Sword();
Weapon fireSword = new FireEnchantment(sword);
fireSword.attack();

特点:递归嵌套,层层增强

代理模式(武器店老板)
// 武器店代理
public class WeaponShopProxy implements Weapon {
    private RealWeaponShop shop;
    private boolean access;
    
    public WeaponShopProxy(boolean vip) {
        this.access = vip;
    }
    
    public void attack() {
        if (access) {
            if (shop == null) {
                shop = new RealWeaponShop(); // 延迟加载
            }
            shop.attack();
        } else {
            System.out.println("非VIP不能使用神器");
        }
    }
}

特点:控制访问,可能不直接转发

核心差异

  • 装饰者:重在增强功能
  • 代理:重在控制访问

三、快速选择指南

遇到问题时的选择思路:

  1. 创建对象

    • 简单创建 → 简单工厂
    • 需要扩展 → 工厂方法
    • 创建套装 → 抽象工厂
    • 复杂构造 → 建造者
  2. 行为管理

    • 主动切换算法 → 策略模式
    • 自动状态流转 → 状态模式
    • 固定流程模板 → 模板方法
  3. 对象增强

    • 功能叠加 → 装饰者
    • 访问控制 → 代理
    • 接口转换 → 适配器

四、记忆口诀

  1. 工厂三兄弟

    • 简单工厂:一个工厂啥都造
    • 工厂方法:一个产品一工厂
    • 抽象工厂:一套产品一工厂
  2. 观察 vs 发布订阅

    • 观察者:直接打电话
    • 发布订阅:群里发公告
  3. 策略 vs 状态

    • 策略:我选武器
    • 状态:武器自动变形
  4. 装饰者 vs 代理

    • 装饰者:套娃增强
    • 代理:门卫把关

五、总结

设计模式的区别就像不同的工具:

  • 螺丝刀和锤子:虽然都是工具,但用途不同
  • 不同型号螺丝刀:适合不同规格的螺丝

关键区分点:

  1. 意图:这个模式要解决什么问题?
  2. 关系:类之间如何交互?
  3. 变化点:什么是可变的?什么是稳定的?

记住:没有最好的模式,只有最适合的模式。就像不能拿螺丝刀当锤子用,根据实际场景选择合适的设计模式才是正道!