当前位置: 首页 > news >正文

23种设计模式

23种设计模式总结(大白话,适合小白),完整例子讲解,明白怎么用,什么时候用,对比优缺点,不同之处

23种设计模式大白话总结(适合小白)

设计模式是解决代码问题的“经典套路”,就像烹饪的固定配方。以下是最通俗的解释+生活例子+代码片段,帮你快速理解每种模式的核心思想、适用场景和优缺点,并对比不同模式的区别!


一、创建型模式(5种)

核心目标:解决对象创建的问题,让代码灵活生成实例。

1. 单例模式(Singleton)

是什么:确保一个类只有一个实例,全局可访问。
例子:数据库连接池、全局配置对象。
代码

java

public class Singleton {private static Singleton instance;private Singleton() {} // 私有构造public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}
}

何时用:需要严格控制实例数量时(如共享资源)。
优点:节省内存,避免重复创建。
缺点:多线程需加锁(可用双重检查锁优化)。


2. 工厂方法模式(Factory Method)

是什么:定义一个创建对象的接口,让子类决定实例化哪个类。
例子:物流系统,不同运输方式(卡车、轮船)由不同子工厂创建。
代码

java

interface Transport {void deliver();
}
class Truck implements Transport {public void deliver() { System.out.println("陆运"); }
}
class Ship implements Transport {public void deliver() { System.out.println("海运"); }
}// 工厂接口
interface Logistics {Transport createTransport();
}
class RoadLogistics implements Logistics {public Transport createTransport() { return new Truck(); }
}
class SeaLogistics implements Logistics {public Transport createTransport() { return new Ship(); }
}

何时用:需要解耦对象创建和使用时。
优点:扩展性强(新增运输方式只需加子类)。
缺点:每新增一个产品就要新增一个工厂类。


3. 抽象工厂模式(Abstract Factory)

是什么:创建成套相关对象(如GUI组件:按钮+文本框)。
例子:Windows风格工厂生产Windows按钮和文本框,Mac工厂生产Mac风格组件。
代码

java

interface Button { void render(); }
interface TextBox { void input(); }// Windows 系列组件
class WinButton implements Button {public void render() { System.out.println("Windows 按钮"); }
}
class WinTextBox implements TextBox {public void input() { System.out.println("Windows 输入框"); }
}// Mac 系列组件
class MacButton implements Button {public void render() { System.out.println("Mac 按钮"); }
}
class MacTextBox implements TextBox {public void input() { System.out.println("Mac 输入框"); }
}// 抽象工厂
interface GUIFactory {Button createButton();TextBox createTextBox();
}
class WinFactory implements GUIFactory {public Button createButton() { return new WinButton(); }public TextBox createTextBox() { return new WinTextBox(); }
}
class MacFactory implements GUIFactory {public Button createButton() { return new MacButton(); }public TextBox createTextBox() { return new MacTextBox(); }
}

何时用:需要保证产品兼容性时。
优点:产品族一致性高。
缺点:新增产品族需修改所有工厂。


4. 建造者模式(Builder)

是什么:分步骤构造复杂对象,支持灵活组合参数。
例子:组装电脑(CPU、内存、硬盘可自定义)。
代码

java

class Computer {private String CPU;private String RAM;// 私有构造,只能通过Builder创建private Computer(Builder builder) {this.CPU = builder.CPU;this.RAM = builder.RAM;}// 建造者public static class Builder {private String CPU;private String RAM;public Builder setCPU(String cpu) { this.CPU = cpu; return this; }public Builder setRAM(String ram) { this.RAM = ram; return this; }public Computer build() { return new Computer(this); }}
}// 使用
Computer myPC = new Computer.Builder().setCPU("Intel i9").setRAM("32GB").build();

何时用:对象构造参数多且可选时。
优点:避免构造方法过长。
缺点:代码量增加。


5. 原型模式(Prototype)

是什么:通过克隆现有对象创建新对象(而非new)。
例子:游戏中的怪物快速复制。
代码

java

class Monster implements Cloneable {private String type;public Monster(String type) { this.type = type; }@Overridepublic Monster clone() throws CloneNotSupportedException {return (Monster) super.clone();}
}// 使用
Monster dragon = new Monster("Dragon");
Monster dragon2 = dragon.clone(); // 克隆而不是新建

何时用:对象创建成本高时(如数据库初始化)。
优点:性能高(比new快)。
缺点:深拷贝需额外处理。


二、结构型模式(7种)

结构型设计模式主要解决如何组合类和对象来形成更大的结构,同时保持灵活性和可复用性。

核心目标:解决类和对象的组合问题,优化代码结构。

6. 适配器模式(Adapter)

是什么:让不兼容的接口协同工作。
例子:Type-C转3.5mm耳机转接头。
代码

java

// 旧接口(3.5mm耳机)
interface OldHeadphone {void playSound();
}
// 新接口(Type-C)
interface TypeC {void transmitDigital();
}
// 适配器
class Adapter implements OldHeadphone {private TypeC typeC;public Adapter(TypeC typeC) { this.typeC = typeC; }public void playSound() {typeC.transmitDigital(); // 调用新接口的方法}
}

何时用:旧系统兼容新接口时,整合老代码或第三方库时接口不兼容。
优点:无需修改原有代码,让不兼容的类一起工作。
缺点:增加调用层级,代码复杂度增加。


7. 装饰器模式(Decorator)

是什么:动态给对象添加功能(替代继承)。
例子:给人穿不同衣服(装饰),给咖啡加糖、加牛奶。
代码

java

// 基础接口
interface Coffee {int cost();
}// 基础实现
class BasicCoffee implements Coffee {@Overridepublic int cost() {return 10;}
}// 装饰器基类
abstract class CoffeeDecorator implements Coffee {protected Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}
}// 具体装饰器(加糖)
class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic int cost() {return coffee.cost() + 2;}
}// 使用
public class Main {public static void main(String[] args) {Coffee coffee = new BasicCoffee();coffee = new SugarDecorator(coffee);System.out.println(coffee.cost()); // 输出12}
}

何时用:不想用继承,但需要动态扩展功能,需要灵活扩展对象功能时。
优点:灵活,避免继承导致的类爆炸。
缺点:多层装饰复杂,可能难调试。


8. 代理模式(Proxy)

是什么:通过代理控制对象访问(如权限验证)。
例子:延迟加载图片。
代码

java

interface Image {void display();
}// 真实图片
class RealImage implements Image {private String filename;public RealImage(String filename) {this.filename = filename;loadFromDisk();}private void loadFromDisk() {System.out.println("加载图片: " + filename);}@Overridepublic void display() {System.out.println("显示图片: " + filename);}
}// 代理类
class ProxyImage implements Image {private String filename;private RealImage realImage;public ProxyImage(String filename) {this.filename = filename;}@Overridepublic void display() {if (realImage == null) {realImage = new RealImage(filename);}realImage.display();}
}// 使用
public class Main {public static void main(String[] args) {Image image = new ProxyImage("photo.jpg");image.display(); // 第一次真正加载image.display(); // 直接使用缓存}
}

何时用:需要延迟加载或权限控制时。
优点:解耦客户端和实际对象,保护目标对象。
缺点:增加请求处理时间。


9. 组合模式(Composite)

是什么:统一处理单个对象和组合对象,用树形结构表示“部分-整体”关系。
例子:文件系统(文件夹包含文件/子文件夹)。
代码

java

interface Component {void operation();
}// 叶子节点(文件)
class Leaf implements Component {@Overridepublic void operation() {System.out.println("执行叶子节点操作");}
}// 组合节点(文件夹)
class Composite implements Component {private List<Component> children = new ArrayList<>();public void add(Component component) {children.add(component);}@Overridepublic void operation() {for (Component child : children) {child.operation();}}
}// 使用
public class Main {public static void main(String[] args) {Composite root = new Composite();root.add(new Leaf());root.add(new Leaf());root.operation(); // 输出两次叶子操作}
}

何时用:处理树形结构(菜单、文件系统)。
优点:统一处理单个对象和组合对象。
缺点:设计抽象,业务复杂时难实现,叶子节点可能被迫实现不相关的方法。


10. 桥接模式(Bridge)

是什么:将抽象与实现分离,各自独立变化。
例子:不同颜色和形状的图形(如红色圆形、蓝色方形)。
代码

java

abstract class Shape {protected Color color;public Shape(Color color) { this.color = color; }
}
class Circle extends Shape { /* 具体实现 */ }

java

// 实现部分(渲染器)
interface Renderer {void renderCircle(int radius);
}class VectorRenderer implements Renderer {@Overridepublic void renderCircle(int radius) {System.out.println("矢量圆,半径" + radius);}
}// 抽象部分(形状)
abstract class Shape {protected Renderer renderer;public Shape(Renderer renderer) {this.renderer = renderer;}abstract void draw();
}class Circle extends Shape {private int radius;public Circle(Renderer renderer, int radius) {super(renderer);this.radius = radius;}@Overridevoid draw() {renderer.renderCircle(radius);}
}// 使用
public class Main {public static void main(String[] args) {Renderer vectorRenderer = new VectorRenderer();Circle circle = new Circle(vectorRenderer, 5);circle.draw(); // 输出矢量圆,半径5}
}

何时用:避免多层继承,独立扩展不同维度,多维度变化的场景。
优点:减少类数量,灵活扩展,解耦抽象和实现。
缺点:设计复杂度高。


11. 享元模式(Flyweight)

是什么:共享大量细粒度对象(如文字处理中的字符库),共享对象以减少内存占用。
例子:游戏中的重复小兵模型共享。
代码

java

class Bullet {private final String type; // 内部状态(可共享)public Bullet(String type) {this.type = type;}public void fire(int x, int y) { // 外部状态由参数传递System.out.println(type + "子弹发射到(" + x + "," + y + ")");}
}class BulletFactory {private static final Map<String, Bullet> bullets = new HashMap<>();public static Bullet getBullet(String type) {if (!bullets.containsKey(type)) {bullets.put(type, new Bullet(type));}return bullets.get(type);}
}// 使用
public class Main {public static void main(String[] args) {Bullet bullet1 = BulletFactory.getBullet("9mm");Bullet bullet2 = BulletFactory.getBullet("9mm");System.out.println(bullet1 == bullet2); // 输出truebullet1.fire(100, 200);}
}

何时用:系统有大量相似对象时,需要减少内存开销时。
优点:节省内存,大幅降低内存占用。
缺点:需要区分内部/外部状态。


12. 外观模式(Facade)

是什么:提供一个简化接口,隐藏系统复杂性,为复杂子系统提供统一入口。
例子:一键启动电脑(封装开机自检、加载系统等步骤)。
代码

java

class CPU {void start() { System.out.println("CPU启动"); }
}class Memory {void start() { System.out.println("内存启动"); }
}// 外观类(一键开机)
class ComputerFacade {private CPU cpu;private Memory memory;public ComputerFacade() {cpu = new CPU();memory = new Memory();}public void start() {cpu.start();memory.start();}
}// 使用
public class Main {public static void main(String[] args) {ComputerFacade computer = new ComputerFacade();computer.start(); // 隐藏复杂步骤}
}

何时用:简化客户端调用复杂系统时。
优点:降低使用复杂度。
缺点:不符合开闭原则(修改需改外观类),外观类可能变成“上帝类”。


三、行为型模式(11种)

行为型设计模式主要解决 对象之间的交互和职责分配,让代码更灵活、可维护。

核心目标:解决对象间的交互与职责分配问题。

13. 观察者模式(Observer)

是什么:一对多依赖,对象状态变化时通知所有依赖者。
例子:微信公众号(发布文章时通知所有订阅用户)。
代码

java

// 观察者接口
interface Subscriber {void update(String message);
}// 被观察者(主题)
class WeChatPublicAccount {private List<Subscriber> subscribers = new ArrayList<>();public void addSubscriber(Subscriber sub) {subscribers.add(sub);}public void notifySubscribers(String message) {for (Subscriber sub : subscribers) {sub.update(message);}}
}// 具体观察者
class User implements Subscriber {private String name;public User(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " 收到消息:" + message);}
}// 使用
public class Main {public static void main(String[] args) {WeChatPublicAccount account = new WeChatPublicAccount();account.addSubscriber(new User("张三"));account.addSubscriber(new User("李四"));account.notifySubscribers("新文章发布了!");}
}

何时用:需要动态联动多个对象时。
优点:解耦观察者和被观察者。
缺点:通知顺序可能影响效率。


14. 策略模式(Strategy)

是什么:封装算法族,可动态切换。
例子:支付方式(支付宝、微信、银行卡)。
代码

java

// 策略接口
interface PaymentStrategy {void pay(int amount);
}// 具体策略
class Alipay implements PaymentStrategy {@Overridepublic void pay(int amount) {System.out.println("支付宝支付:" + amount + "元");}
}class WechatPay implements PaymentStrategy {@Overridepublic void pay(int amount) {System.out.println("微信支付:" + amount + "元");}
}// 上下文(使用策略的类)
class ShoppingCart {private PaymentStrategy strategy;public void setStrategy(PaymentStrategy strategy) {this.strategy = strategy;}public void checkout(int amount) {strategy.pay(amount);}
}// 使用
public class Main {public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();cart.setStrategy(new Alipay());cart.checkout(100);  // 支付宝支付:100元}
}

何时用:需要灵活替换算法时。
优点:避免多重条件判断。
缺点:策略类数量多。


15. 模板方法模式(Template Method)

是什么:定义算法骨架,子类实现细节。
例子:咖啡和茶的制作流程(烧水、冲泡、加料)。
代码

java

abstract class Beverage {// 模板方法(固定流程)public final void prepare() {boilWater();brew();pourInCup();addCondiments();}void boilWater() {System.out.println("烧水");}abstract void brew();       // 子类实现abstract void addCondiments();void pourInCup() {System.out.println("倒入杯子");}
}class Coffee extends Beverage {@Overridevoid brew() {System.out.println("冲泡咖啡粉");}@Overridevoid addCondiments() {System.out.println("加糖和牛奶");}
}// 使用
public class Main {public static void main(String[] args) {Beverage coffee = new Coffee();coffee.prepare();  // 执行模板方法}
}

何时用:多个子类有公共流程时。
优点:代码复用性强。
缺点:子类可能影响父类逻辑。


16. 责任链模式(Chain of Responsibility)

是什么:将请求沿处理链传递,直到被处理。
例子:审批流程(员工→经理→CEO)。
代码

java

// 处理者接口
interface Handler {void setNext(Handler next);void handleRequest(int amount);
}// 具体处理者
class GroupLeader implements Handler {private Handler next;@Overridepublic void setNext(Handler next) {this.next = next;}@Overridepublic void handleRequest(int amount) {if (amount <= 1000) {System.out.println("组长审批通过");} else if (next != null) {next.handleRequest(amount);}}
}class Manager implements Handler {private Handler next;@Overridepublic void setNext(Handler next) {this.next = next;}@Overridepublic void handleRequest(int amount) {if (amount <= 5000) {System.out.println("经理审批通过");} else if (next != null) {next.handleRequest(amount);}}
}// 使用
public class Main {public static void main(String[] args) {Handler groupLeader = new GroupLeader();Handler manager = new Manager();groupLeader.setNext(manager);groupLeader.handleRequest(3000);  // 经理审批通过}
}

何时用:请求需多级处理时。
优点:解耦请求和处理者。
缺点:链长时性能低。


17. 状态模式(State)

是什么:对象行为随内部状态改变而改变。
例子:订单状态(待支付→已发货→已完成)。
代码

java

// 状态接口
interface State {void handle();
}// 具体状态
class OnState implements State {@Overridepublic void handle() {System.out.println("灯已开");}
}class OffState implements State {@Overridepublic void handle() {System.out.println("灯已关");}
}// 上下文(状态持有者)
class LightSwitch {private State state;public void setState(State state) {this.state = state;}public void press() {state.handle();}
}// 使用
public class Main {public static void main(String[] args) {LightSwitch light = new LightSwitch();light.setState(new OffState());light.press();  // 灯已关light.setState(new OnState());light.press();  // 灯已开}
}

何时用:对象有多个状态且行为不同时。
优点:取代大量if-else判断。
缺点:状态类数量多。


18. 命令模式(Command)

是什么:将请求封装为对象,支持撤销、排队。
例子:遥控器按键(每个按键对应一个命令)。
代码

java

// 命令接口
interface Command {void execute();
}// 具体命令(开灯)
class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.turnOn();}
}// 接收者(实际执行操作的对象)
class Light {public void turnOn() {System.out.println("灯亮了");}
}// 调用者(遥控器按钮)
class RemoteControl {private Command command;public void setCommand(Command command) {this.command = command;}public void pressButton() {command.execute();}
}// 使用
public class Main {public static void main(String[] args) {Light light = new Light();Command lightOn = new LightOnCommand(light);RemoteControl remote = new RemoteControl();remote.setCommand(lightOn);remote.pressButton();  // 灯亮了}
}

何时用:需要记录操作历史或支持撤销时。
优点:解耦请求发起者和执行者。
缺点:命令类膨胀36。


19. 中介者模式(Mediator)

是什么:通过中介对象管理多个对象交互。
例子:聊天室(用户不直接对话,通过服务器中转)。
代码

java

class ChatRoom {public static void send(User user, String msg) { /* 转发消息 */ }
}

何时用:多对象交互复杂时。
优点:减少类间依赖。
缺点:中介类可能过于复杂。


20. 访问者模式(Visitor)

是什么:在不修改类的前提下,为类添加新操作。
例子:超市商品计价(不同商品类型用不同计价策略)。
代码

java

// 元素接口(商品)
interface Product {void accept(Visitor visitor);
}// 具体元素
class Book implements Product {@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}public double getPrice() {return 50.0;}
}// 访问者接口
interface Visitor {void visit(Book book);
}// 具体访问者(价格计算)
class PriceVisitor implements Visitor {@Overridepublic void visit(Book book) {System.out.println("书的价格:" + book.getPrice());}
}// 使用
public class Main {public static void main(String[] args) {Product book = new Book();Visitor visitor = new PriceVisitor();book.accept(visitor);  // 书的价格:50.0}
}

何时用:需为复杂对象结构添加新功能时。
优点:符合开闭原则。
缺点:增加新元素类困难。


21. 备忘录模式(Memento)

是什么:保存对象状态,支持回滚。
例子:游戏存档。
代码

java

复制

class Game {private String state;public Memento save() { return new Memento(state); }public void load(Memento m) { state = m.getState(); }
}

何时用:需要撤销/恢复功能时。
优点:状态保存与业务逻辑分离。
缺点:消耗内存。


22. 迭代器模式(Iterator)

是什么:提供统一方式遍历集合元素。
例子:遍历书架的书籍(隐藏底层存储结构)。
代码

java

复制

interface Iterator { boolean hasNext(); Object next();
}

何时用:需要统一遍历不同数据结构时。
优点:隐藏集合内部实现。
缺点:增加额外类。


23. 解释器模式(Interpreter)

是什么:定义语法规则,解释特定语言。
例子:SQL解析、数学表达式计算。
代码

java

复制

interface Expression { int interpret(Context context); }
class Add implements Expression {private Expression left, right;public int interpret(Context c) { return left.interpret(c) + right.interpret(c); }
}

何时用:需要解析特定语法时。
优点:易于扩展语法规则。
缺点:复杂语法难维护。


四、模式对比与总结

1. 创建型模式对比

模式核心思想典型应用场景
单例模式全局唯一实例配置管理、线程池
工厂方法子类决定创建对象物流运输、支付方式
抽象工厂创建成套对象跨平台UI组件库
建造者分步骤构造复杂对象自定义电脑配置
原型模式克隆代替新建游戏怪物生成

2. 行为型模式对比

对比总结

模式核心区别适用场景
适配器转换接口,让旧代码兼容新系统接口不兼容
装饰器动态添加功能,不修改原类灵活扩展功能
代理控制访问(权限、延迟加载)保护或优化访问
组合统一处理树形结构的节点菜单、文件系统
外观简化复杂系统的调用入口提供简洁接口
桥接分离抽象和实现,避免类爆炸多维度独立变化
享元共享对象,减少内存占用大量重复对象

如何选择

  • 要兼容接口?→ 适配器

  • 动态加功能?→ 装饰器

  • 控制访问?→ 代理

  • 处理树形结构?→ 组合

  • 简化复杂调用?→ 外观

  • 避免多维继承?→ 桥接

  • 节省内存?→ 享元

实际应用场景

  • 适配器:Java 的 InputStreamReader 将字节流转换为字符流。

  • 装饰器:Java IO 中的 BufferedReader 包装 FileReader

  • 代理:Spring AOP 中的动态代理。

  • 享元:Java 的 String 常量池。

3. 结构型模式对比

对比总结

模式核心区别适用场景
策略模式动态切换算法(如支付方式)多种算法需要灵活替换
观察者模式一对多依赖通知(如消息订阅)对象状态变化通知其他对象
责任链模式链式处理请求(如审批流程)请求需要多个对象处理
命令模式封装请求为对象(如遥控器按钮)请求参数化、队列化
模板方法模式固定流程,子类实现细节(如冲泡饮料)多个类有相同流程但不同步骤
状态模式对象行为随状态改变(如电灯开关)对象状态影响行为
访问者模式分离算法与对象结构(如统计商品价格)对复杂结构执行多种操作

如何选择

  • 需要动态切换算法 → 策略模式

  • 状态变化通知其他对象 → 观察者模式

  • 请求需要多级处理 → 责任链模式

  • 封装请求为对象 → 命令模式

  • 固定流程但有不同步骤 → 模板方法模式

  • 行为随状态改变 → 状态模式

  • 对复杂结构执行多种操作 → 访问者模式

实际应用场景

  • 策略模式:Java 的 Comparator 接口排序不同对象。

  • 观察者模式:Java 的 Swing 事件监听。

  • 责任链模式:Servlet 中的过滤器链。

  • 命令模式:Java 的 Runnable 接口。


五、如何选择设计模式?

  1. 先明确问题类型:创建对象?组合结构?行为交互?

  2. 查看模式适用场景:如需要全局唯一实例→单例;需要灵活扩展算法→策略。

  3. 权衡优缺点:如单例节省内存但难扩展,工厂模式灵活但增加类数量。

http://www.xdnf.cn/news/193879.html

相关文章:

  • STM32N6570-DK ISP调试
  • UDP 报文结构与注意事项总结
  • 每日c/c++题 备战蓝桥杯(P1093 [NOIP 2007 普及组] 奖学金)
  • 勘破养生伪常识,开启科学养生新篇
  • 发那科机器人(基本操作、坐标系、I/O通信)
  • JVM——引入
  • STM32裸机编程架构与思路
  • LangChain4j +DeepSeek大模型应用开发——2 接入其他大模型
  • 练习普通话,说话更有节奏
  • Odoo 18 中计划、待办、项目管理模块解析
  • re题(49)BUUCTF-crackMe
  • 【深度剖析】贵州茅台的数字化转型(2025)(中1)
  • Spring的BeanFactory和FactoryBean的区别
  • springboot dev process
  • JVM模型、GC、OOM定位
  • [250428] Nginx 1.28.0 发布:性能优化、安全增强及新特性
  • wps批注线条怎么取消去掉wps批注后有竖线
  • CentOS7——Docker部署java服务
  • 基于常微分方程的神经网络(Neural ODE)
  • 如何通过Google Chrome增强网页内容的安全性
  • 低空经济无人机创新实训室解决方案
  • 亚马逊环保标识运营指南:抢占流量新赛道的6大策略解析
  • 读论文《Deep learning-assited pulsed discharge plasma catalysis modeling》2023 ECM
  • Android Studio 2024版,前进返回按钮丢失解决
  • springboot项目之websocket的坑:spring整合websocket后进行单元测试后报错的解决方案
  • Qt6.8.2中WebAssembly沙盒环境中预加载文件
  • Cursor
  • 可视化图解算法:合并二叉树
  • JVM 生产环境问题定位与解决实战(八):实战篇——正则表达式回溯引发的CPU 100%
  • C++20 小语法