设计模式
Java 中常见的 23 种设计模式通常分为三大类 :创建型、结构型和行为型。 它们是面向对象设计中解决特定问题的经典方案,能极大地提高代码的可复用性、可维护性和灵活性。
- 创建型模式(5种)
关注对象的创建机制,使系统在创建对象时更加灵活:
单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式 - 结构型模式(7种)
关注类和对象的组合,形成更大的结构:
适配器模式、装饰器模式、代理模式、桥接模式、组合模式、外观模式、享元模式、过滤器模式 - 行为型模式(11种)
关注对象之间的职责分配和通信:
观察者模式、责任链模式、模板方法模式、状态模式、命令模式、访问者模式、中介者模式、迭代器模式、备忘录模式、解释器模式、策略模式
一、创建型设计模式(5种)
核心思想: 将对象的创建与使用分离,使系统更符合"单一职责"原则。
1.单例模式
意图: 保证一个类仅有一个实例,并提供一个全局访问点。
场景: 线程池、缓存、日志对象、对话框、打印机驱动等。
java
//懒汉模式
public class Singleton {
// 私有静态实例,防止被引用
private static volatile Singleton instance = null;
// 私有构造方法,防止外部实例化
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (Singleton.class) {
if (instance == null) { // 第二次检查
instance = new Singleton();
}
}
}
return instance;
}
}
// 使用枚举实现(最简洁、安全,防止反射攻击)
public enum SingletonEnum {
INSTANCE;
public void doSomething() {
System.out.println("Doing something...");
}
}
2. 工厂方法模式
意图: 定义一个创建对象的接口,但让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
场景: 日志记录器、数据库访问等。
java
// 1. 产品接口
interface Product {
void use();
}
// 2. 具体产品
class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("Using Product A");
}
}
class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("Using Product B");
}
}
// 3. 创建者抽象类
abstract class Creator {
public abstract Product factoryMethod();
public void someOperation() {
Product product = factoryMethod();
product.use();
}
}
// 4. 具体创建者
class ConcreteCreatorA extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductA();
}
}
class ConcreteCreatorB extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductB();
}
}
3. 抽象工厂模式
意图: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
场景: 支持不同主题的 UI 组件(如 Windows 和 Mac 的按钮、文本框)。
java
// 1. 抽象产品族
interface Button {
void paint();
}
interface Checkbox {
void paint();
}
// 2. 具体产品族
class WinButton implements Button {
@Override
public void paint() { System.out.println("Windows Button"); }
}
class MacButton implements Button {
@Override
public void paint() { System.out.println("Mac Button"); }
}
class WinCheckbox implements Checkbox {
@Override
public void paint() { System.out.println("Windows Checkbox"); }
}
class MacCheckbox implements Checkbox {
@Override
public void paint() { System.out.println("Mac Checkbox"); }
}
// 3. 抽象工厂
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
// 4. 具体工厂
class WinFactory implements GUIFactory {
@Override
public Button createButton() { return new WinButton(); }
@Override
public Checkbox createCheckbox() { return new WinCheckbox(); }
}
class MacFactory implements GUIFactory {
@Override
public Button createButton() { return new MacButton(); }
@Override
public Checkbox createCheckbox() { return new MacCheckbox(); }
}
4. 建造者模式
意图: 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
场景: 创建复杂的对象,这些对象内部由多个部分组成,且各部分需要精确组装。
java
// 要构建的复杂产品
static class Computer {
private String CPU;
private String RAM;
// ... 更多部件
// 私有构造器,只能通过Builder构建
private Computer(Builder builder) {
this.CPU = builder.CPU;
this.RAM = builder.RAM;
}
// 静态内部类 Builder
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);
}
}
}
public static void main(String[] args) {
// 使用
Computer computer = new Computer.Builder()
.setCPU("Intel i7")
.setRAM("16GB")
.build();
}
5. 原型模式
意图: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
场景: 创建成本高,或初始化需消耗大量资源,且与已有对象相似。
java
// 实现 Cloneable 接口
class Prototype implements Cloneable {
private String field;
public Prototype(String field) {
this.field = field;
}
@Override
public Prototype clone() {
try {
return (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(); // Can't happen
}
}
public String getField() {
return field;
}
}
// 使用
Prototype original = new Prototype("original");
Prototype copy = original.clone();
二、结构型模式 (7种)
核心思想: 关注类和对象的组合,形成更大的结构。
1. 适配器模式
意图: 将一个类的接口转换成客户希望的另外一个接口。
场景: 使用不兼容的类、旧系统改造。
java
// 目标接口(客户期望的接口)
interface Target {
void request();
}
// 需要被适配的类
class Adaptee {
public void specificRequest() {
System.out.println("Adaptee's specific request");
}
}
// 适配器
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest(); // 调用被适配者的方法
}
}
2. 桥接模式
意图: 将抽象部分与它的实现部分分离,使它们都可以独立地变化。
场景: 不同平台上的窗口、不同形状和颜色的图形。
java
// 实现化接口
interface DrawingAPI {
void drawCircle(double x, double y, double radius);
}
// 具体实现化A
class DrawingAPI1 implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius) {
System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
}
}
// 具体实现化B
class DrawingAPI2 implements DrawingAPI {
@Override
public void drawCircle(double x, double y, double radius) {
System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
}
}
// 抽象化
abstract class Shape {
protected DrawingAPI drawingAPI;
protected Shape(DrawingAPI drawingAPI) {
this.drawingAPI = drawingAPI;
}
public abstract void draw();
}
// 扩展抽象化
class CircleShape extends Shape {
private double x, y, radius;
public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
super(drawingAPI);
this.x = x; this.y = y; this.radius = radius;
}
@Override
public void draw() {
drawingAPI.drawCircle(x, y, radius);
}
}
3. 组合模式
意图: 将对象组合成树形结构以表示"部分-整体"的层次结构。使得用户对单个对象和组合对象的使用具有一致性。
场景: 文件系统、菜单、公司组织架构。
java
// 组件接口
interface Component {
void operation();
}
// 叶子节点
class Leaf implements Component {
private String name;
public Leaf(String name) { this.name = name; }
@Override
public void operation() {
System.out.println("Leaf " + name + " operation.");
}
}
// 复合节点
class Composite implements Component {
private List<Component> children = new ArrayList<>();
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
@Override
public void operation() {
for (Component child : children) {
child.operation();
}
}
}
4. 装饰器模式
意图: 动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
场景: Java I/O 流、Servlet API 中的 HttpServletRequestWrapper。
java
// 组件接口
interface Coffee {
double getCost();
String getDescription();
}
// 具体组件
class SimpleCoffee implements Coffee {
@Override
public double getCost() { return 1.0; }
@Override
public String getDescription() { return "Simple coffee"; }
}
// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public double getCost() {
return decoratedCoffee.getCost();
}
@Override
public String getDescription() {
return decoratedCoffee.getDescription();
}
}
// 具体装饰器
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double getCost() {
return super.getCost() + 0.5;
}
@Override
public String getDescription() {
return super.getDescription() + ", Milk";
}
}
5. 外观模式
意图: 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
场景: 简化复杂系统的调用。
java
// 子系统A
class SubSystemA {
public void operationA() {
System.out.println("SubSystemA operation");
}
}
// 子系统B
class SubSystemB {
public void operationB() {
System.out.println("SubSystemB operation");
}
}
// 外观类
class Facade {
private SubSystemA a = new SubSystemA();
private SubSystemB b = new SubSystemB();
public void wrapOperation() {
a.operationA();
b.operationB();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.wrapOperation(); // 只需调用一个方法
}
}
6. 享元模式
意图: 运用共享技术有效地支持大量细粒度的对象。
场景: 文本编辑器中的字符对象、数据库连接池。
java
// 享元接口
interface Flyweight {
void operation(String extrinsicState);
}
// 具体享元
class ConcreteFlyweight implements Flyweight {
private String intrinsicState; // 内部状态,可共享
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(String extrinsicState) {
System.out.println("Intrinsic: " + intrinsicState + ", Extrinsic: " + extrinsicState);
}
}
// 享元工厂
class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
flyweights.put(key, new ConcreteFlyweight(key));
}
return flyweights.get(key);
}
}
7. 代理模式
意图: 为其他对象提供一种代理以控制对这个对象的访问。
场景: 远程代理、虚拟代理(延迟加载)、保护代理(权限控制)、智能引用。
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("Loading " + filename);
}
@Override
public void display() {
System.out.println("Displaying " + filename);
}
}
// 代理类
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();
}
}
三、行为型模式 (11种)
核心思想: 关注对象之间的职责分配和通信。
1. 责任链模式
意图: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
场景: 审批流程、异常处理、Java Servlet 中的 Filter。
java
// 处理器抽象类
abstract class Handler {
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(int request);
}
// 具体处理器
class ConcreteHandler1 extends Handler {
@Override
public void handleRequest(int request) {
if (request >= 0 && request < 10) {
System.out.println("Handler1 handled request " + request);
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
class ConcreteHandler2 extends Handler {
@Override
public void handleRequest(int request) {
if (request >= 10 && request < 20) {
System.out.println("Handler2 handled request " + request);
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
2. 命令模式
意图: 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
场景: 图形界面中的菜单、事务、任务队列。
java
// 命令接口
interface Command {
void execute();
}
// 接收者
class Light {
public void turnOn() {
System.out.println("Light is on");
}
public void turnOff() {
System.out.println("Light is off");
}
}
// 具体命令
class TurnOnCommand implements Command {
private Light light;
public TurnOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
}
class TurnOffCommand implements Command {
private Light light;
public TurnOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
}
// 调用者
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
3. 解释器模式
意图: 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
场景: 正则表达式、SQL 解析、数学表达式计算。(使用较少,因为通常有更高效的方式)
java
// 抽象表达式
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 expr1;
private Expression expr2;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
// 使用
public class InterpreterPatternDemo {
public static void main(String[] args) {
Expression robert = new TerminalExpression("Robert");
Expression john = new TerminalExpression("John");
Expression or = new OrExpression(robert, john);
System.out.println(or.interpret("John")); // true
System.out.println(or.interpret("Robert")); // true
System.out.println(or.interpret("Alice")); // false
}
}
4. 迭代器模式
意图: 提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
场景: Java 集合框架中的 Iterator。
java
// 迭代器接口
interface Iterator<T> {
boolean hasNext();
T next();
}
// 聚合接口
interface Container {
Iterator getIterator();
}
// 具体聚合类
class NameRepository implements Container {
public String[] names = {"Robert", "John", "Julie", "Lora"};
@Override
public Iterator getIterator() {
return new NameIterator();
}
// 具体迭代器
private class NameIterator implements Iterator<String> {
int index;
@Override
public boolean hasNext() {
return index < names.length;
}
@Override
public String next() {
if (this.hasNext()) {
return names[index++];
}
return null;
}
}
}
5. 中介者模式
意图: 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
场景: 聊天室、机场控制系统、MVC 框架中的控制器。
java
// 中介者接口
interface ChatMediator {
void sendMessage(String msg, User user);
void addUser(User user);
}
// 具体中介者
class ChatRoom implements ChatMediator {
private List<User> users;
public ChatRoom() {
this.users = new ArrayList<>();
}
@Override
public void addUser(User user) {
this.users.add(user);
}
@Override
public void sendMessage(String msg, User user) {
for (User u : this.users) {
// 消息不应该发给发送者自己
if (u != user) {
u.receive(msg);
}
}
}
}
// 抽象同事类
abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator med, String name) {
this.mediator = med;
this.name = name;
}
public abstract void send(String msg);
public abstract void receive(String msg);
}
// 具体同事类
class ChatUser extends User {
public ChatUser(ChatMediator med, String name) {
super(med, name);
}
@Override
public void send(String msg) {
System.out.println(this.name + " Sending: " + msg);
mediator.sendMessage(msg, this);
}
@Override
public void receive(String msg) {
System.out.println(this.name + " Received: " + msg);
}
}
6. 备忘录模式
意图: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
场景: 游戏存档、文本编辑器撤销。
java
// 备忘录
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 String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
// 管理者
class CareTaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento state) {
mementoList.add(state);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
7. 观察者模式
意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
场景: 事件驱动系统、MVC 模型、发布-订阅。
java
import java.util.*;
// 主题(被观察者)
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// 具体主题
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyObservers();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
// 观察者
interface Observer {
void update();
}
// 具体观察者
class ConcreteObserver implements Observer {
private ConcreteSubject subject;
public ConcreteObserver(ConcreteSubject subject) {
this.subject = subject;
this.subject.registerObserver(this);
}
@Override
public void update() {
System.out.println("Observer notified! New state: " + subject.getState());
}
}
8. 状态模式
意图: 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
场景: 订单状态、线程状态、游戏角色状态。
java
// 状态接口
interface State {
void handle(Context context);
}
// 具体状态A
class ConcreteStateA implements State {
@Override
public void handle(Context context) {
System.out.println("Handling in State A");
context.setState(new ConcreteStateB()); // 切换到状态B
}
}
// 具体状态B
class ConcreteStateB implements State {
@Override
public void handle(Context context) {
System.out.println("Handling in State B");
context.setState(new ConcreteStateA()); // 切换回状态A
}
}
// 上下文
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
9. 策略模式
意图: 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
场景: 支付方式、排序算法、压缩算法。
java
// 策略接口
interface Strategy {
int doOperation(int num1, int num2);
}
// 具体策略
class OperationAdd implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
class OperationSubtract implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
// 上下文
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
10. 模板方法模式
意图: 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
场景: JDBC 模板、Servlet 的 service 方法。
java
// 抽象类
abstract class Game {
// 模板方法,定义为 final 防止子类重写
public final void play() {
initialize();
startPlay();
endPlay();
}
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
}
// 具体子类
class Cricket extends Game {
@Override
void initialize() {
System.out.println("Cricket Game Initialized!");
}
@Override
void startPlay() {
System.out.println("Cricket Game Started.");
}
@Override
void endPlay() {
System.out.println("Cricket Game Finished!");
}
}
class Football extends Game {
@Override
void initialize() {
System.out.println("Football Game Initialized!");
}
@Override
void startPlay() {
System.out.println("Football Game Started.");
}
@Override
void endPlay() {
System.out.println("Football Game Finished!");
}
}
11. 访问者模式
意图: 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
场景: 编译器语法树处理、文档结构处理。
java
import java.util.*;
// 元素接口
interface ComputerPart {
void accept(ComputerPartVisitor visitor);
}
// 具体元素
class Keyboard implements ComputerPart {
@Override
public void accept(ComputerPartVisitor visitor) {
visitor.visit(this);
}
}
class Monitor implements ComputerPart {
@Override
public void accept(ComputerPartVisitor visitor) {
visitor.visit(this);
}
}
// 访问者接口
interface ComputerPartVisitor {
void visit(Keyboard keyboard);
void visit(Monitor monitor);
}
// 具体访问者
class ComputerPartDisplayVisitor implements ComputerPartVisitor {
@Override
public void visit(Keyboard keyboard) {
System.out.println("Displaying Keyboard.");
}
@Override
public void visit(Monitor monitor) {
System.out.println("Displaying Monitor.");
}
}
// 对象结构
class Computer implements ComputerPart {
ComputerPart[] parts;
public Computer() {
parts = new ComputerPart[] {new Keyboard(), new Monitor()};
}
@Override
public void accept(ComputerPartVisitor visitor) {
for (ComputerPart part : parts) {
part.accept(visitor);
}
}
}