以下是Java 23种设计模式的详细解析,包含意图、特点、实现要点及代码演示,按创建型、结构型、行为型分类整理:
一、创建型模式(5种)
专注于对象创建机制,隐藏创建逻辑,提高灵活性。
1. 单例模式(Singleton)
- 意图:确保一个类仅有一个实例,并提供全局访问点。
- 特点:
- 唯一实例,全局可访问;
- 避免频繁创建销毁,节省资源;
- 需处理线程安全问题。
- 实现要点:
- 私有构造器阻止外部实例化;
- 静态方法/变量持有唯一实例。
// 饿汉式(线程安全,类加载时初始化)
public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {} // 私有构造器public static Singleton getInstance() { return INSTANCE; }
}// 懒汉式(双重校验锁,延迟初始化)
public class LazySingleton {private static volatile LazySingleton instance;private LazySingleton() {}public static LazySingleton getInstance() {if (instance == null) {synchronized (LazySingleton.class) {if (instance == null) {instance = new LazySingleton();}}}return instance;}
}
2. 工厂模式(Factory)
- 意图:通过工厂类封装对象创建逻辑,客户端无需关注具体实现。
- 特点:
- 解耦对象创建与使用;
- 新增产品只需扩展工厂,符合开闭原则;
- 适用于产品类型较少的场景。
- 实现要点:
- 定义产品接口;
- 工厂类根据参数返回具体产品实例。
// 产品接口
interface Shape { void draw(); }// 具体产品
class Circle implements Shape {@Override public void draw() { System.out.println("画圆形"); }
}// 工厂类
class ShapeFactory {public Shape getShape(String type) {if (type.equalsIgnoreCase("CIRCLE")) return new Circle();return null;}
}// 使用
public class FactoryDemo {public static void main(String[] args) {ShapeFactory factory = new ShapeFactory();factory.getShape("CIRCLE").draw(); // 输出:画圆形}
}
3. 抽象工厂模式(Abstract Factory)
- 意图:创建一系列相关或依赖的产品族,无需指定具体类。
- 特点:
- 针对“产品族”(如“现代家具”包含椅子、桌子);
- 切换产品族只需更换工厂,客户端无需修改;
- 新增产品需修改工厂接口,灵活性较低。
- 实现要点:
- 抽象工厂定义产品族的创建方法;
- 具体工厂实现特定产品族的创建。
// 抽象产品
interface Chair { void sit(); }
interface Table { void put(); }// 具体产品(现代风格)
class ModernChair implements Chair {@Override public void sit() { System.out.println("坐现代椅子"); }
}// 抽象工厂
interface FurnitureFactory {Chair createChair();Table createTable();
}// 具体工厂
class ModernFactory implements FurnitureFactory {@Override public Chair createChair() { return new ModernChair(); }@Override public Table createTable() { return new ModernTable(); }
}// 使用
public class AbstractFactoryDemo {public static void main(String[] args) {FurnitureFactory factory = new ModernFactory();factory.createChair().sit(); // 输出:坐现代椅子}
}
4. 建造者模式(Builder)
- 意图:分步构建复杂对象,分离构建过程与最终表示。
- 特点:
- 步骤清晰,支持定制对象的不同部件;
- 同一构建过程可生成不同产品;
- 由指挥者控制构建顺序。
- 实现要点:
- 建造者接口定义部件构建方法;
- 指挥者调用建造者方法完成组装。
// 产品
class Computer {private String cpu;private String ram;// getter/setter省略
}// 建造者接口
interface ComputerBuilder {void buildCpu();void buildRam();Computer getResult();
}// 具体建造者(高配电脑)
class HighEndBuilder implements ComputerBuilder {private Computer computer = new Computer();@Override public void buildCpu() { computer.setCpu("i9"); }@Override public void buildRam() { computer.setRam("32GB"); }@Override public Computer getResult() { return computer; }
}// 指挥者
class Director {public Computer construct(ComputerBuilder builder) {builder.buildCpu();builder.buildRam();return builder.getResult();}
}// 使用
public class BuilderDemo {public static void main(String[] args) {Computer computer = new Director().construct(new HighEndBuilder());System.out.println(computer.getCpu()); // 输出:i9}
}
5. 原型模式(Prototype)
- 意图:通过复制现有对象创建新对象,避免重复初始化。
- 特点:
- 简化创建流程,适合初始化耗时的对象;
- 分为浅拷贝(引用类型共享)和深拷贝(完全复制);
- 无需知道类名即可创建对象。
- 实现要点:
- 实现
Cloneable
接口; - 重写
clone()
方法实现复制逻辑。
- 实现
class Sheep implements Cloneable {private String name;public Sheep(String name) { this.name = name; }@Override protected Sheep clone() throws CloneNotSupportedException {return (Sheep) super.clone(); // 浅拷贝}
}// 使用
public class PrototypeDemo {public static void main(String[] args) throws CloneNotSupportedException {Sheep original = new Sheep("多利");Sheep clone = original.clone();System.out.println(clone.name); // 输出:多利}
}
二、结构型模式(7种)
处理类或对象的组合,优化结构以实现功能复用。
6. 适配器模式(Adapter)
- 意图:将一个类的接口转换为客户端期望的另一个接口。
- 特点:
- 解决接口不兼容问题(如旧系统对接新系统);
- 分为类适配器(继承)和对象适配器(组合,更灵活);
- 不修改原有代码,符合开闭原则。
- 实现要点:
- 适配器实现目标接口;
- 内部持有适配者实例,转发请求。
// 目标接口
interface Target { void request(); }// 适配者
class Adaptee {public void specificRequest() { System.out.println("适配者方法"); }
}// 适配器
class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) { this.adaptee = adaptee; }@Override public void request() { adaptee.specificRequest(); }
}// 使用
public class AdapterDemo {public static void main(String[] args) {Target target = new Adapter(new Adaptee());target.request(); // 输出:适配者方法}
}
7. 装饰器模式(Decorator)
- 意图:动态给对象添加额外功能,不改变其结构。
- 特点:
- 比继承更灵活,可多层嵌套装饰;
- 装饰器与被装饰者实现同一接口,客户端透明;
- 适用于功能扩展频繁的场景(如IO流)。
- 实现要点:
- 装饰器抽象类实现组件接口,并持有组件实例;
- 具体装饰器扩展额外功能。
// 抽象组件
interface Coffee {String getDesc();double cost();
}// 具体组件(基础咖啡)
class SimpleCoffee implements Coffee {@Override public String getDesc() { return "纯咖啡"; }@Override public double cost() { return 5.0; }
}// 装饰器
class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) { super(coffee); }@Override public String getDesc() { return super.getDesc() + " + 牛奶"; }@Override public double cost() { return super.cost() + 2.0; }
}// 使用
public class DecoratorDemo {public static void main(String[] args) {Coffee coffee = new MilkDecorator(new SimpleCoffee());System.out.println(coffee.getDesc() + ":" + coffee.cost()); // 纯咖啡 + 牛奶:7.0}
}
8. 代理模式(Proxy)
- 意图:为对象提供代理,控制对原对象的访问。
- 特点:
- 代理与目标对象实现同一接口,客户端无感知;
- 可实现权限控制、延迟加载、日志记录等;
- 分为静态代理和动态代理(如JDK Proxy)。
- 实现要点:
- 代理类持有目标对象引用;
- 代理方法中添加额外逻辑后调用目标方法。
// 抽象主题
interface Image { void display(); }// 真实主题(耗时操作)
class RealImage implements Image {private String filename;public RealImage(String filename) { this.filename = filename; load(); }private void load() { System.out.println("加载图片:" + filename); }@Override public void display() { System.out.println("显示图片"); }
}// 代理类(延迟加载)
class ProxyImage implements Image {private RealImage realImage;private String filename;public ProxyImage(String filename) { this.filename = filename; }@Override public void display() {if (realImage == null) realImage = new RealImage(filename);realImage.display();}
}// 使用
public class ProxyDemo {public static void main(String[] args) {Image image = new ProxyImage("photo.jpg");image.display(); // 首次:加载并显示;再次:直接显示}
}
9. 外观模式(Facade)
- 意图:为子系统提供统一接口,简化客户端访问。
- 特点:
- 封装子系统复杂性,提供“一站式”接口;
- 隔离客户端与子系统,降低耦合;
- 不改变子系统内部逻辑。
- 实现要点:
- 外观类持有子系统实例;
- 提供高层方法封装子系统交互。
// 子系统
class DVDPlayer { public void on() { System.out.println("DVD打开"); } }
class Projector { public void on() { System.out.println("投影仪打开"); } }// 外观类
class HomeTheaterFacade {private DVDPlayer dvd;private Projector projector;public HomeTheaterFacade(DVDPlayer dvd, Projector projector) {this.dvd = dvd;this.projector = projector;}public void watchMovie() {projector.on();dvd.on();}
}// 使用
public class FacadeDemo {public static void main(String[] args) {new HomeTheaterFacade(new DVDPlayer(), new Projector()).watchMovie();// 输出:投影仪打开 → DVD打开}
}
10. 桥接模式(Bridge)
- 意图:分离抽象与实现,使两者可独立变化。
- 特点:
- 解决抽象与实现的多对多继承问题(避免类爆炸);
- 抽象层与实现层通过组合关联,而非继承;
- 适合跨维度扩展场景(如“形状”与“颜色”)。
- 实现要点:
- 抽象类持有实现接口的引用;
- 抽象类的方法通过实现接口完成。
// 实现接口(颜色)
interface Color { void apply(); }
class Red implements Color { @Override public void apply() { System.out.println("红色"); } }// 抽象类(形状)
abstract class Shape {protected Color color;public Shape(Color color) { this.color = color; }abstract void draw();
}// 具体抽象(圆形)
class Circle extends Shape {public Circle(Color color) { super(color); }@Override void draw() {System.out.print("画圆形,颜色:");color.apply();}
}// 使用
public class BridgeDemo {public static void main(String[] args) {new Circle(new Red()).draw(); // 输出:画圆形,颜色:红色}
}
11. 组合模式(Composite)
- 意图:将对象组合成树形结构,统一处理单个对象和组合对象。
- 特点:
- 树形结构中,叶子节点与组合节点统一接口;
- 支持递归遍历(如文件系统的文件与文件夹);
- 客户端无需区分叶子与组合,操作一致。
- 实现要点:
- 抽象组件定义统一接口;
- 组合节点持有子组件列表,实现添加/删除/遍历。
// 抽象组件
interface Component {void operation();void add(Component c);
}// 叶子节点(文件)
class File implements Component {private String name;public File(String name) { this.name = name; }@Override public void operation() { System.out.println("文件:" + name); }@Override public void add(Component c) {} // 叶子不支持添加
}// 组合节点(文件夹)
class Folder implements Component {private List<Component> children = new ArrayList<>();private String name;public Folder(String name) { this.name = name; }@Override public void operation() {System.out.println("文件夹:" + name);children.forEach(Component::operation);}@Override public void add(Component c) { children.add(c); }
}// 使用
public class CompositeDemo {public static void main(String[] args) {Folder root = new Folder("根目录");root.add(new File("a.txt"));root.operation(); // 输出:文件夹:根目录 → 文件:a.txt}
}
12. 享元模式(Flyweight)
- 意图:共享细粒度对象,减少内存消耗。
- 特点:
- 区分“内部状态”(共享,如颜色)和“外部状态”(非共享,如位置);
- 通过享元池管理共享对象,避免重复创建;
- 适合对象数量多、重复度高的场景(如围棋棋子)。
- 实现要点:
- 享元工厂负责创建和缓存享元对象;
- 外部状态通过方法参数传入。
// 享元接口
interface Shape { void draw(int x, int y); }// 具体享元(圆形)
class Circle implements Shape {private String color; // 内部状态public Circle(String color) { this.color = color; }@Override public void draw(int x, int y) { // 外部状态System.out.println("圆形(" + color + ") at (" + x + "," + y + ")");}
}// 享元工厂
class ShapeFactory {private static final Map<String, Shape> circles = new HashMap<>();public static Shape getCircle(String color) {return circles.computeIfAbsent(color, k -> {System.out.println("创建" + color + "圆形");return new Circle(color);});}
}// 使用
public class FlyweightDemo {public static void main(String[] args) {Shape red1 = ShapeFactory.getCircle("红色");Shape red2 = ShapeFactory.getCircle("红色"); // 复用red1.draw(10, 20); // 圆形(红色) at (10,20)}
}
三、行为型模式(11种)
关注对象间的通信、职责分配和行为交互。
13. 策略模式(Strategy)
- 意图:定义算法族,使其可互换,客户端可动态选择。
- 特点:
- 算法独立封装,易于扩展(新增策略只需实现接口);
- 解决“if-else”过多导致的代码臃肿;
- 客户端需知道所有策略类。
- 实现要点:
- 策略接口定义算法方法;
- 上下文持有策略引用,动态切换策略。
// 策略接口
interface Payment { void pay(int amount); }// 具体策略(支付宝)
class Alipay implements Payment {@Override public void pay(int amount) { System.out.println("支付宝支付:" + amount); }
}// 上下文
class ShoppingCart {private Payment payment;public void setPayment(Payment payment) { this.payment = payment; }public void checkout(int amount) { payment.pay(amount); }
}// 使用
public class StrategyDemo {public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();cart.setPayment(new Alipay());cart.checkout(100); // 输出:支付宝支付:100}
}
14. 模板方法模式(Template Method)
- 意图:定义算法骨架,子类实现具体步骤。
- 特点:
- 固定流程,灵活定制步骤(如游戏的初始化→开始→结束);
- 父类调用子类方法(好莱坞原则:“别找我,我找你”);
- 符合开闭原则(扩展步骤而非修改骨架)。
- 实现要点:
- 抽象父类定义模板方法(包含固定步骤);
- 抽象方法由子类实现具体逻辑。
// 抽象模板
abstract class Game {abstract void initialize();abstract void start();// 模板方法(固定流程)public final void play() {initialize();start();}
}// 具体实现(足球)
class Football extends Game {@Override void initialize() { System.out.println("足球初始化"); }@Override void start() { System.out.println("足球开始"); }
}// 使用
public class TemplateDemo {public static void main(String[] args) {new Football().play(); // 输出:足球初始化 → 足球开始}
}
15. 观察者模式(Observer)
- 意图:对象间一对多依赖,当一个对象变化时通知所有依赖者。
- 特点:
- 松耦合:主题无需知道观察者细节;
- 支持动态添加/移除观察者;
- 适合事件驱动场景(如GUI事件、消息通知)。
- 实现要点:
- 主题维护观察者列表,提供注册/移除/通知方法;
- 观察者实现更新接口,接收主题通知。
// 主题接口
interface Subject {void register(Observer o);void notifyObservers(String msg);
}// 观察者接口
interface Observer { void update(String msg); }// 具体主题(公众号)
class WechatSubject implements Subject {private List<Observer> observers = new ArrayList<>();@Override public void register(Observer o) { observers.add(o); }@Override public void notifyObservers(String msg) {observers.forEach(o -> o.update(msg));}
}// 具体观察者(用户)
class User implements Observer {private String name;public User(String name) { this.name = name; }@Override public void update(String msg) {System.out.println(name + "收到:" + msg);}
}// 使用
public class ObserverDemo {public static void main(String[] args) {WechatSubject subject = new WechatSubject();subject.register(new User("张三"));subject.notifyObservers("新文章发布"); // 张三收到:新文章发布}
}
16. 迭代器模式(Iterator)
- 意图:提供遍历集合的统一接口,无需暴露内部结构。
- 特点:
- 客户端无需关心集合类型(列表、树等),通过迭代器遍历;
- 支持多种遍历方式(正向、反向);
- 符合单一职责原则(集合负责存储,迭代器负责遍历)。
- 实现要点:
- 迭代器接口定义
hasNext()
和next()
方法; - 集合提供获取迭代器的方法。
- 迭代器接口定义
// 迭代器接口
interface Iterator {boolean hasNext();Object next();
}// 集合接口
interface Container { Iterator getIterator(); }// 具体集合(名字列表)
class NameContainer implements Container {private String[] names = {"A", "B", "C"};@Override public Iterator getIterator() {return new NameIterator();}private class NameIterator implements Iterator {int index = 0;@Override public boolean hasNext() { return index < names.length; }@Override public Object next() { return names[index++]; }}
}// 使用
public class IteratorDemo {public static void main(String[] args) {Container container = new NameContainer();Iterator it = container.getIterator();while (it.hasNext()) { System.out.println(it.next()); } // A、B、C}
}
17. 责任链模式(Chain of Responsibility)
- 意图:将请求沿处理链传递,直到被处理。
- 特点:
- 发送者与接收者解耦,无需知道谁处理请求;
- 可动态调整链结构(如审批流程:组长→经理→总监);
- 可能导致请求未被处理。
- 实现要点:
- 处理器持有下一个处理器引用;
- 每个处理器判断是否处理请求,否则传递给下一个。
// 抽象处理器
abstract class Handler {protected Handler next;public void setNext(Handler next) { this.next = next; }abstract void handle(int request);
}// 处理1-10
class Handler1 extends Handler {@Override void handle(int request) {if (request <= 10) System.out.println("Handler1处理:" + request);else if (next != null) next.handle(request);}
}// 处理11-20
class Handler2 extends Handler {@Override void handle(int request) {if (request <= 20) System.out.println("Handler2处理:" + request);else if (next != null) next.handle(request);}
}// 使用
public class ChainDemo {public static void main(String[] args) {Handler h1 = new Handler1();Handler h2 = new Handler2();h1.setNext(h2);h1.handle(5); // Handler1处理:5h1.handle(15); // Handler2处理:15}
}
18. 命令模式(Command)
- 意图:将请求封装为对象,使请求可参数化、队列化或撤销。
- 特点:
- 解耦请求发送者与接收者(如遥控器与灯);
- 支持命令排队、日志记录、事务回滚;
- 新增命令只需实现接口,扩展性好。
- 实现要点:
- 命令接口定义
execute()
方法; - 具体命令持有接收者引用,调用其方法。
- 命令接口定义
// 命令接口
interface Command { void execute(); }// 接收者(灯)
class Light {public void on() { System.out.println("灯亮"); }
}// 具体命令(开灯)
class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) { this.light = light; }@Override public void execute() { light.on(); }
}// 调用者(遥控器)
class Remote {private Command command;public void setCommand(Command command) { this.command = command; }public void press() { command.execute(); }
}// 使用
public class CommandDemo {public static void main(String[] args) {Remote remote = new Remote();remote.setCommand(new LightOnCommand(new Light()));remote.press(); // 输出:灯亮}
}
19. 备忘录模式(Memento)
- 意图:保存对象状态,以便后续恢复。
- 特点:
- 封装状态存储细节,原发器无需暴露内部状态;
- 适合游戏存档、编辑器撤销等场景;
- 需平衡内存开销(过多快照占用资源)。
- 实现要点:
- 备忘录存储原发器状态;
- 管理者负责保存和恢复备忘录。
// 备忘录
class Memento {private String state;public Memento(String state) { this.state = state; }public String getState() { return state; }
}// 原发器
class Originator {private String state;public void setState(String state) { this.state = state; }public Memento save() { return new Memento(state); }public void restore(Memento m) { state = m.getState(); }
}// 管理者
class CareTaker {private Memento memento;public void save(Memento m) { memento = m; }public Memento get() { return memento; }
}// 使用
public class MementoDemo {public static void main(String[] args) {Originator o = new Originator();CareTaker c = new CareTaker();o.setState("状态1");c.save(o.save()); // 保存o.setState("状态2");o.restore(c.get()); // 恢复为状态1}
}
20. 状态模式(State)
- 意图:允许对象在内部状态变化时改变行为,类似状态机。
- 特点:
- 将状态逻辑封装到不同状态类,避免“if-else”堆砌;
- 状态转换清晰,可由状态类或上下文控制;
- 适合状态较多且转换复杂的场景(如订单状态)。
- 实现要点:
- 状态接口定义行为方法;
- 上下文持有当前状态,委托状态对象处理行为。
// 状态接口
interface State { void doAction(Context context); }// 具体状态(开启)
class StartState implements State {@Override public void doAction(Context context) {System.out.println("系统开启");context.setState(this);}
}// 上下文
class Context {private State state;public void setState(State state) { this.state = state; }
}// 使用
public class StateDemo {public static void main(String[] args) {Context context = new Context();new StartState().doAction(context); // 输出:系统开启}
}
21. 访问者模式(Visitor)
- 意图:在不修改对象结构的前提下,为对象添加新操作。
- 特点:
- 分离“数据结构”与“操作行为”,新操作只需新增访问者;
- 适合数据结构稳定但操作多变的场景(如报表统计);
- 修改结构需修改所有访问者,灵活性低。
- 实现要点:
- 元素接口定义
accept(Visitor)
方法; - 访问者接口定义对每个元素的操作方法。
- 元素接口定义
// 元素接口
interface Element { void accept(Visitor v); }// 具体元素(员工A)
class EmployeeA implements Element {@Override public void accept(Visitor v) { v.visit(this); }
}// 访问者接口
interface Visitor { void visit(EmployeeA a); }// 具体访问者(计算工资)
class SalaryVisitor implements Visitor {@Override public void visit(EmployeeA a) {System.out.println("计算员工A工资");}
}// 使用
public class VisitorDemo {public static void main(String[] args) {Element e = new EmployeeA();e.accept(new SalaryVisitor()); // 输出:计算员工A工资}
}
22. 中介者模式(Mediator)
- 意图:用中介者封装对象间的交互,减少直接依赖。
- 特点:
- 将网状依赖转为星状依赖,降低复杂度;
- 集中管理交互逻辑,便于维护;
- 中介者可能成为“上帝类”,需避免逻辑过重。
- 实现要点:
- 中介者接口定义交互方法;
- 同事类持有中介者引用,通过中介者通信。
// 中介者接口
interface Mediator { void send(String msg, Colleague c); }// 同事类
abstract class Colleague {protected Mediator mediator;public Colleague(Mediator m) { mediator = m; }
}// 具体同事(用户1)
class User1 extends Colleague {public User1(Mediator m) { super(m); }public void send(String msg) { mediator.send(msg, this); }public void receive(String msg) { System.out.println("User1收到:" + msg); }
}// 具体中介者(聊天室)
class ChatMediator implements Mediator {private User1 u1;private User2 u2;@Override public void send(String msg, Colleague c) {if (c == u1) u2.receive(msg);else u1.receive(msg);}
}// 使用
public class MediatorDemo {public static void main(String[] args) {Mediator m = new ChatMediator();User1 u1 = new User1(m);User2 u2 = new User2(m);u1.send("你好"); // User2收到:你好}
}
23. 解释器模式(Interpreter)
- 意图:定义语言语法的解释器,用于解析特定格式的语句。
- 特点:
- 适合简单语法(如正则表达式、表达式计算);
- 语法复杂时会导致类爆炸(如SQL解析);
- 可扩展新语法规则。
- 实现要点:
- 抽象表达式定义解释方法;
- 终结符表达式处理基本语法单元,非终结符表达式处理组合语法。
// 抽象表达式
interface Expression { boolean interpret(String context); }// 终结符表达式(匹配单个字符)
class TerminalExpression implements Expression {private String data;public TerminalExpression(String data) { this.data = data; }@Override public boolean interpret(String context) {return context.contains(data);}
}// 非终结符表达式(或运算)
class OrExpression implements Expression {private Expression e1, e2;public OrExpression(Expression e1, Expression e2) {this.e1 = e1;this.e2 = e2;}@Override public boolean interpret(String context) {return e1.interpret(context) || e2.interpret(context);}
}// 使用
public class InterpreterDemo {public static void main(String[] args) {Expression expr = new OrExpression(new TerminalExpression("a"), new TerminalExpression("b"));System.out.println(expr.interpret("abc")); // true(含a)}
}
总结
设计模式是解决特定问题的成熟方案,核心价值在于:
- 创建型:控制对象创建,降低耦合;
- 结构型:优化类/对象组合,实现复用;
- 行为型:规范对象交互,明确职责。
实际开发中需结合业务场景选择,避免过度设计。