设计模式:行为型(Behavioral)
责任链模式(Chain of Responsibility Pattern)
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它用于将请求的发送者和接收者解耦,从而可以让多个对象都有机会处理请求,形成一条处理请求的责任链。在责任链模式中,每个处理者对象都可以处理请求,如果当前处理者不能处理请求,则将请求传递给下一个处理者,直到有一个处理者能够处理请求或者请求到达链的末端。
责任链模式主要解决的问题是在一个对象链中,解耦请求的发送者和接收者,使得多个对象都有机会处理请求,并且可以动态地改变请求的处理顺序。责任链模式可以避免将请求的处理逻辑硬编码在一个对象中,使得代码更加灵活、可扩展和可维护。
责任链模式的核心组件包括抽象处理者(Handler)、具体处理者(ConcreteHandler)和客户端(Client)三部分。抽象处理者定义了处理请求的接口和责任链的下一个处理者的引用,具体处理者实现了抽象处理者的接口并负责处理请求,客户端创建责任链并将请求发送给第一个处理者。
以下是一个简单的责任链模式的例子,假设有三个处理者分别用于处理低级、中级和高级的请求:

1 // 抽象处理者 2 abstract class Handler { 3 protected Handler nextHandler; // 下一个处理者 4 5 public void setNextHandler(Handler nextHandler) { 6 this.nextHandler = nextHandler; 7 } 8 9 public abstract void handleRequest(int level); 10 } 11 12 // 具体处理者 13 class ConcreteHandler1 extends Handler { 14 @Override 15 public void handleRequest(int level) { 16 if (level <= 10) { 17 System.out.println("ConcreteHandler1处理了请求"); 18 } else if (nextHandler != null) { 19 nextHandler.handleRequest(level); 20 } 21 } 22 } 23 24 class ConcreteHandler2 extends Handler { 25 @Override 26 public void handleRequest(int level) { 27 if (level > 10 && level <= 20) { 28 System.out.println("ConcreteHandler2处理了请求"); 29 } else if (nextHandler != null) { 30 nextHandler.handleRequest(level); 31 } 32 } 33 } 34 35 class ConcreteHandler3 extends Handler { 36 @Override 37 public void handleRequest(int level) { 38 if (level > 20) { 39 System.out.println("ConcreteHandler3处理了请求"); 40 } else if (nextHandler != null) { 41 nextHandler.handleRequest(level); 42 } 43 } 44 } 45 46 // 客户端 47 public class Client { 48 public static void main(String[] args) { 49 Handler handler1 = new ConcreteHandler1(); 50 Handler handler2 = new ConcreteHandler2(); 51 Handler handler3 = new ConcreteHandler3(); 52 53 handler1.setNextHandler(handler2); 54 handler2.setNextHandler(handler3); 55 56 // 发送请求 57 handler1.handleRequest(5); 58 handler1.handleRequest(15); 59 handler1.handleRequest(25); 60 } 61 }
在上面的例子中,三个具体处理者分别处理了不同范围的请求,如果一个处理者无法处理请求,它会将请求传递给下一个处理者,直到有一个处理者能够处理请求或者请求到达责任链的末端。
在这个例子中,ConcreteHandler1处理低级的请求(level <= 10),ConcreteHandler2处理中级的请求(10 < level <= 20),ConcreteHandler3处理高级的请求(level > 20)。客户端通过设置处理者的nextHandler形成了一条责任链,并通过调用handleRequest方法发送请求到责任链的起始处,从而实现了请求的处理。
责任链模式在实际应用中可以用于处理请求的多级处理场景,例如在Web应用中的请求过滤器链、日志记录链、权限验证链等场景中都可以使用责任链模式。它可以帮助将处理逻辑解耦,使得系统更加灵活、可扩展和易于维护。
命令模式(Command Pattern)
命令模式是一种行为型设计模式,用于将请求发送者和请求接收者解耦,将请求封装成一个独立的对象,从而允许请求的发送者在不知道具体请求接收者的情况下,通过调用请求对象来间接地执行请求。
命令模式包含以下角色:
-
Command(命令):定义了执行请求的接口,通常包含一个execute()方法,用于执行具体的请求。
-
ConcreteCommand(具体命令):实现了Command接口,负责实现具体的请求逻辑,并持有一个接收者对象,用于执行具体的操作。
-
Receiver(接收者):负责具体的请求处理逻辑,实现了请求的实际执行。
-
Invoker(调用者):负责调用命令对象来执行请求,持有命令对象的引用。
-
Client(客户端):负责创建具体的命令对象并设置其接收者,同时将命令对象传递给调用者。
命令模式的核心思想是将请求封装成一个对象,从而实现请求发送者和请求接收者的解耦,使得请求的发送者只需要与抽象的命令接口进行交互,而不需要了解具体的请求接收者和其处理逻辑。这样可以实现请求的参数化和动态化,提高系统的灵活性和可维护性。
一个简单的命令模式的例子是电视遥控器,遥控器上的按钮相当于请求发送者,遥控器的每个按钮对应一个具体的命令对象,命令对象负责封装具体的操作(例如打开电视、关闭电视、切换频道等)和接收者(电视对象),遥控器持有命令对象的引用并通过调用命令对象的execute()方法来间接地执行具体的操作。这样,遥控器和电视之间解耦,遥控器不需要直接调用电视对象的方法来控制电视的操作,而是通过命令对象来间接地执行。

1 // Command(命令):定义了执行文本编辑器操作的接口,例如 Command 接口。 2 public interface Command { 3 void execute(); 4 } 5 6 // ConcreteCommand(具体命令):实现了 Command 接口,负责具体的文本编辑器操作,例如 CopyCommand、CutCommand、PasteCommand 等。 7 public class CopyCommand implements Command { 8 private TextEditor textEditor; 9 10 public CopyCommand(TextEditor textEditor) { 11 this.textEditor = textEditor; 12 } 13 14 @Override 15 public void execute() { 16 textEditor.copy(); 17 } 18 } 19 20 public class CutCommand implements Command { 21 private TextEditor textEditor; 22 23 public CutCommand(TextEditor textEditor) { 24 this.textEditor = textEditor; 25 } 26 27 @Override 28 public void execute() { 29 textEditor.cut(); 30 } 31 } 32 33 public class PasteCommand implements Command { 34 private TextEditor textEditor; 35 36 public PasteCommand(TextEditor textEditor) { 37 this.textEditor = textEditor; 38 } 39 40 @Override 41 public void execute() { 42 textEditor.paste(); 43 } 44 } 45 46 // Receiver(接收者):负责实际执行文本编辑器操作的类,例如 TextEditor 类。 47 public class TextEditor { 48 public void copy() { 49 System.out.println("执行复制操作"); 50 } 51 52 public void cut() { 53 System.out.println("执行剪切操作"); 54 } 55 56 public void paste() { 57 System.out.println("执行粘贴操作"); 58 } 59 } 60 61 // Invoker(调用者):负责调用命令对象来执行请求的类,例如 TextEditorInvoker 类。 62 public class TextEditorInvoker { 63 private Command command; 64 65 public void setCommand(Command command) { 66 this.command = command; 67 } 68 69 public void executeCommand() { 70 command.execute(); 71 } 72 } 73 74 // Client(客户端):负责创建具体的命令对象并设置其接收者,同时将命令对象传递给调用者,例如 Client 类。 75 public class Client { 76 public static void main(String[] args) { 77 // 创建接收者 78 TextEditor textEditor = new TextEditor(); 79 80 // 创建具体命令对象并设置其接收者 81 Command copyCommand = new CopyCommand(textEditor); 82 Command cutCommand = new CutCommand(textEditor); 83 Command pasteCommand = new PasteCommand(textEditor); 84 85 // 创建调用者并设置命令对象 86 TextEditorInvoker invoker = new TextEditorInvoker(); 87 invoker.setCommand(copyCommand); 88 invoker.executeCommand(); 89 90 invoker.setCommand(cutCommand); 91 invoker.executeCommand(); 92 93 invoker.setCommand(pasteCommand); 94 invoker.executeCommand(); 95 } 96 }
迭代器模式(Iterator Pattern)
迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供一种方法来遍历集合对象中的元素,而不需要暴露集合的内部结构。通过使用迭代器模式,可以让客户端在不了解集合内部结构的情况下,遍历集合中的元素。
迭代器模式的主要角色包括:
-
抽象迭代器(Iterator):定义了访问和遍历集合中元素的接口,包括 hasNext() 方法判断是否还有下一个元素,和 next() 方法返回下一个元素。
-
具体迭代器(Concrete Iterator):实现了抽象迭代器接口,负责实现对具体集合的遍历逻辑。
-
抽象集合(Aggregate):定义了集合对象的接口,包括创建迭代器的方法 createIterator()。
-
具体集合(Concrete Aggregate):实现了抽象集合接口,负责创建具体迭代器对象,实现对集合的遍历。
迭代器模式的核心思想是将遍历集合的责任封装到迭代器对象中,从而实现了集合和遍历算法的解耦。客户端只需要通过迭代器对象来访问集合中的元素,而不需要关心集合的内部结构。
以下是一个简单的迭代器模式的示例,假设有一个存储了字符串的集合对象,可以使用迭代器模式来遍历并访问这些字符串:

1 // 抽象迭代器 2 interface Iterator { 3 boolean hasNext(); 4 String next(); 5 } 6 7 // 具体迭代器 8 class StringIterator implements Iterator { 9 private String[] strings; 10 private int index; 11 12 public StringIterator(String[] strings) { 13 this.strings = strings; 14 this.index = 0; 15 } 16 17 @Override 18 public boolean hasNext() { 19 return index < strings.length; 20 } 21 22 @Override 23 public String next() { 24 if (hasNext()) { 25 return strings[index++]; 26 } 27 return null; 28 } 29 } 30 31 // 抽象集合 32 interface Aggregate { 33 Iterator createIterator(); 34 } 35 36 // 具体集合 37 class StringCollection implements Aggregate { 38 private String[] strings; 39 40 public StringCollection(String[] strings) { 41 this.strings = strings; 42 } 43 44 @Override 45 public Iterator createIterator() { 46 return new StringIterator(strings); 47 } 48 }
为什么使用迭代器遍历元素?
-
封装集合内部结构:使用迭代器模式可以将集合的内部结构封装起来,使客户端无需了解集合的实现细节,只需要通过迭代器对象进行遍历操作。
-
统一遍历接口:迭代器模式定义了统一的遍历接口,包括 hasNext() 和 next() 方法,使得客户端在遍历不同类型的集合时可以使用相同的接口,不需要针对不同的集合类型编写不同的遍历逻辑。
-
简化客户端代码:使用迭代器模式可以简化客户端的代码,避免了显式的使用索引或者循环来遍历集合,提供了一种更加简洁和直观的方式来访问集合中的元素。
-
支持多种遍历方式:迭代器模式可以实现多种不同的遍历方式,例如顺序遍历、逆序遍历、跳跃遍历等,而且可以在运行时动态地切换遍历方式,从而灵活地满足不同的需求。
中介者模式(Mediator Pattern)
中介者模式(Mediator Pattern)是一种行为型设计模式,用于减少多个对象之间的直接依赖关系,通过引入一个中介者对象来协调和管理这些对象之间的通信和交互。中介者模式可以帮助对象之间的解耦,从而降低系统的复杂性。
中介者模式的核心思想是将对象之间的交互逻辑封装到中介者对象中,使得各个对象只需要与中介者对象进行通信,而不需要直接与其他对象通信。这样可以避免对象之间的紧耦合关系,使得系统更加灵活、可扩展和易于维护。
中介者模式通常包含以下几个角色:
-
中介者(Mediator):负责协调和管理各个对象之间的通信和交互。通常包含一些公共方法,用于接收和发送消息,并根据消息的内容和类型来决定如何处理。
-
同事类(Colleague):包含一些业务逻辑,需要与其他同事类进行通信和交互。各个同事类之间不直接通信,而是通过中介者来进行间接通信。
中介者模式的优点包括:
-
减少了对象之间的直接依赖关系,使得系统更加灵活和可扩展。
-
将交互逻辑封装到中介者对象中,使得系统的结构更加清晰,易于维护和理解。
-
可以集中管理和控制对象之间的通信和交互,提供了一种集中式的方式来处理复杂的交互逻辑。

1 // 中介者接口 2 public interface ChatRoomMediator { 3 void sendMessage(String message, User user); 4 void addUser(User user); 5 } 6 7 // 具体中介者 8 public class ChatRoom implements ChatRoomMediator { 9 private List<User> users = new ArrayList<>(); 10 11 @Override 12 public void sendMessage(String message, User user) { 13 for (User u : users) { 14 if (u != user) { 15 u.receiveMessage(message); 16 } 17 } 18 } 19 20 @Override 21 public void addUser(User user) { 22 users.add(user); 23 } 24 } 25 26 // 同事类 27 public class User { 28 private String name; 29 private ChatRoomMediator mediator; 30 31 public User(String name, ChatRoomMediator mediator) { 32 this.name = name; 33 this.mediator = mediator; 34 } 35 36 public void sendMessage(String message) { 37 System.out.println(name + " sends message: " + message); 38 mediator.sendMessage(message, this); 39 } 40 41 public void receiveMessage(String message) { 42 System.out.println(name + " receives message: " + message); 43 } 44 } 45 46 // 客户端使用示例 47 public class Client { 48 public static void main(String[] args) { 49 ChatRoomMediator mediator = new ChatRoom(); 50 User user1 = new User("User1", mediator); 51 User user2 = new User("User2", mediator); 52 User user3 = new User("User3", mediator); 53 54 mediator.addUser(user1); 55 mediator.addUser(user2); 56 mediator.addUser(user3); 57 58 user1.sendMessage("Hello, everyone!"); 59 user2.sendMessage("Hi, User1!"); 60 } 61 }
观察者模式(Observer Pattern)
观察者模式(Observer Pattern)是一种行为型设计模式,用于在对象之间建立一种一对多的依赖关系,当一个对象的状态发生变化时,其依赖的多个对象都会得到通知并自动更新。
观察者模式包含以下几个角色:
-
Subject(主题):被观察者,它是一个抽象类或接口,定义了被观察者的一些基本方法,如添加、删除和通知观察者等。
-
ConcreteSubject(具体主题):具体的被观察者实现类,它维护着一组观察者对象,并在状态发生变化时通知观察者。
-
Observer(观察者):观察者,它是一个抽象类或接口,定义了观察者的一些基本方法,如更新状态等。
-
ConcreteObserver(具体观察者):具体的观察者实现类,它实现了观察者的更新方法,以便在接收到被观察者通知时进行相应的处理。
观察者模式的核心思想是通过抽象的主题(被观察者)和观察者之间的关联关系,实现了对象之间的松耦合,使得主题和观察者可以独立地演化和扩展,而不会相互影响。当主题的状态发生变化时,会自动通知所有的观察者进行更新,从而实现了对象之间的一对多依赖关系。

1 import java.util.ArrayList; 2 import java.util.List; 3 4 // 主题(被观察者) 5 interface Subject { 6 void registerObserver(Observer observer); // 注册观察者 7 void unregisterObserver(Observer observer); // 取消注册观察者 8 void notifyObservers(String news); // 通知观察者 9 } 10 11 // 观察者 12 interface Observer { 13 void update(String news); // 更新方法 14 } 15 16 // 具体主题(具体被观察者) 17 class NewsPublisher implements Subject { 18 private List<Observer> observers = new ArrayList<>(); 19 private String news; 20 21 @Override 22 public void registerObserver(Observer observer) { 23 observers.add(observer); 24 } 25 26 @Override 27 public void unregisterObserver(Observer observer) { 28 observers.remove(observer); 29 } 30 31 @Override 32 public void notifyObservers(String news) { 33 this.news = news; 34 for (Observer observer : observers) { 35 observer.update(news); 36 } 37 } 38 } 39 40 // 具体观察者 41 class NewsSubscriber implements Observer { 42 private String name; 43 44 public NewsSubscriber(String name) { 45 this.name = name; 46 } 47 48 @Override 49 public void update(String news) { 50 System.out.println(name + " 收到了新闻:" + news); 51 } 52 } 53 54 public class ObserverPatternExample { 55 public static void main(String[] args) { 56 NewsPublisher publisher = new NewsPublisher(); // 创建新闻发布者 57 58 Observer subscriber1 = new NewsSubscriber("Subscriber 1"); // 创建订阅者1 59 Observer subscriber2 = new NewsSubscriber("Subscriber 2"); // 创建订阅者2 60 61 publisher.registerObserver(subscriber1); // 注册订阅者1 62 publisher.registerObserver(subscriber2); // 注册订阅者2 63 64 publisher.notifyObservers("Breaking News: COVID-19 Vaccine Released!"); // 发布新闻 65 66 publisher.unregisterObserver(subscriber1); // 取消注册订阅者1 67 68 publisher.notifyObservers("Latest News: Economic Growth Forecast Revised!"); // 发布新闻 69 70 } 71 }
状态模式(State Pattern)
状态模式(State Pattern)是一种行为型设计模式,用于通过将对象的状态封装成不同的状态对象,并在对象的状态发生变化时,动态地改变对象的行为。状态模式将对象的行为和状态解耦,使得对象可以根据不同的状态进行不同的行为处理,从而实现状态的变化对对象行为的灵活控制。
状态模式的核心思想是将对象的状态抽象成一个状态接口(或者抽象类),然后将不同的状态实现为具体的状态类,这些状态类可以根据具体的业务需求来进行扩展和修改。对象持有一个当前状态对象的引用,通过该状态对象来处理不同的行为。
状态模式通常包含以下几个角色:
-
上下文(Context):它是持有状态的对象,负责管理状态对象的切换和调用相应的行为。通常包含一个对抽象状态的引用,以及一个对客户端的请求的处理方法。
-
抽象状态(State):定义了状态的接口,通常包含了处理请求的方法。在状态模式中,抽象状态可以是接口或者抽象类,具体的状态类需要实现这些方法。
-
具体状态(Concrete State):实现了抽象状态定义的接口,负责具体的状态行为处理。具体状态类通常会包含对环境对象的引用,用于在处理请求时切换状态或者调用环境对象的方法。
状态模式通过将对象的状态封装成状态对象,使得状态的变化对对象行为的影响局限于具体的状态类,而不会影响到其他状态类。这样可以实现状态的变化对对象行为的灵活控制,从而提高系统的扩展性和可维护性。状态模式通常适用于对象的行为随状态的变化而改变的场景,例如订单状态、用户登录状态等。
假设我们有一个电梯系统,其中电梯可以处于三种状态:停止状态、运行状态和故障状态。在不同的状态下,电梯有不同的行为。我们可以使用状态模式来实现这个电梯系统。

1 // 抽象状态接口 2 public interface ElevatorState { 3 void open(); 4 void close(); 5 void run(); 6 void stop(); 7 } 8 9 // 具体状态类 - 停止状态 10 public class StopState implements ElevatorState { 11 // 实现停止状态下的行为 12 // ... 13 } 14 15 // 具体状态类 - 运行状态 16 public class RunState implements ElevatorState { 17 // 实现运行状态下的行为 18 // ... 19 } 20 21 // 具体状态类 - 故障状态 22 public class FaultState implements ElevatorState { 23 // 实现故障状态下的行为 24 // ... 25 } 26 27 public class ElevatorContext { 28 private ElevatorState currentState; // 当前状态 29 30 // 设置当前状态 31 public void setCurrentState(ElevatorState state) { 32 this.currentState = state; 33 } 34 35 // 处理开门请求 36 public void open() { 37 currentState.open(); 38 } 39 40 // 处理关门请求 41 public void close() { 42 currentState.close(); 43 } 44 45 // 处理运行请求 46 public void run() { 47 currentState.run(); 48 } 49 50 // 处理停止请求 51 public void stop() { 52 currentState.stop(); 53 } 54 } 55 56 public class Client { 57 public static void main(String[] args) { 58 ElevatorContext context = new ElevatorContext(); // 创建电梯环境对象 59 context.setCurrentState(new StopState()); // 初始状态为停止状态 60 61 // 处理电梯请求 62 context.open(); // 开门 63 context.close(); // 关门 64 context.run(); // 运行 65 context.stop(); // 停止 66 } 67 }
策略模式(Strategy Pattern)
策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时动态地选择算法或行为,从而使对象能够根据不同的情境或条件选择不同的策略来完成任务,而不需要在代码中硬编码特定的算法或行为。
策略模式由三个主要角色组成:
-
上下文(Context):负责与客户端进行交互,它持有一个策略对象,并通过策略对象来执行具体的行为。
-
抽象策略(Strategy):定义一个共同的接口或抽象类,用于表示不同策略的通用行为。
-
具体策略(Concrete Strategy):实现了抽象策略定义的接口或抽象类,具体实现了策略模式中定义的不同算法或行为。
一个常见的策略模式的例子是在电商系统中的商品促销活动,其中不同的促销活动可以视为不同的策略,可以根据用户选择或系统配置来动态选择不同的促销策略进行应用。

1 // 抽象策略接口 - 商品促销策略 2 public interface PromotionStrategy { 3 void applyPromotion(double price); 4 } 5 6 // 具体策略类 - 满减促销策略 7 public class FullDiscountPromotionStrategy implements PromotionStrategy { 8 @Override 9 public void applyPromotion(double price) { 10 System.out.println("满减促销活动:原价 " + price + " 元,满100元减20元,优惠后 " + (price - 20) + " 元"); 11 } 12 } 13 14 // 具体策略类 - 折扣促销策略 15 public class DiscountPromotionStrategy implements PromotionStrategy { 16 @Override 17 public void applyPromotion(double price) { 18 System.out.println("折扣促销活动:原价 " + price + " 元,8折优惠后 " + (price * 0.8) + " 元"); 19 } 20 } 21 22 // 上下文类 - 商品 23 public class Product { 24 private double price; // 商品价格 25 private PromotionStrategy promotionStrategy; // 持有一个促销策略对象 26 27 // 设置商品价格 28 public void setPrice(double price) { 29 this.price = price; 30 } 31 32 // 设置促销策略对象 33 public void setPromotionStrategy(PromotionStrategy promotionStrategy) { 34 this.promotionStrategy = promotionStrategy; 35 } 36 37 // 应用促销策略 38 public void applyPromotion() { 39 promotionStrategy.applyPromotion(price); 40 } 41 } 42 43 // 客户端代码 44 public class Client { 45 public static void main(String[] args) { 46 Product product = new Product(); // 创建商品对象 47 product.setPrice(120.0); // 设置商品价格 48 49 // 使用满减促销策略 50 PromotionStrategy fullDiscountPromotion = new FullDiscountPromotionStrategy(); 51 product.setPromotionStrategy(fullDiscountPromotion); 52 product.applyPromotion(); // 应用促销策略 53 54 // 使用折扣促销策略 55 PromotionStrategy discountPromotion = new DiscountPromotionStrategy(); 56 product.setPromotionStrategy(discountPromotion); 57 product.applyPromotion(); // 应用促销策略 58 } 59 }
模板模式(Template Pattern)
模板模式(Template Pattern)是一种行为型设计模式,用于定义一个操作的算法骨架,将一些步骤延迟到子类中实现,从而使子类可以在不改变算法骨架的情况下重新定义某些步骤。
模板模式的核心思想是通过抽象类或接口定义一个模板(Template),其中包含了一个算法的骨架,但留下了一些步骤的实现细节交由子类来实现,从而使得子类可以根据需要灵活地实现这些细节,而不改变算法骨架。
模板模式有以下几个关键角色:
- 抽象模板(Abstract Template):定义一个模板方法,其中包含了算法的骨架,可以包含一些具体方法和抽象方法,抽象方法用于留给子类实现。
- 具体模板(Concrete Template):实现抽象模板中的抽象方法,完成算法的具体步骤。
- 客户端(Client):使用模板方法来调用算法,可以通过调用抽象模板中的模板方法来执行算法,不需要关心算法的具体实现,只需要关心算法的调用和结果。

1 // 抽象模板 - 咖啡制作 2 public abstract class CoffeeMaker { 3 // 制作咖啡 4 public final void makeCoffee() { 5 boilWater(); 6 brewCoffee(); 7 pourInCup(); 8 addCondiments(); 9 System.out.println("咖啡制作完成!"); 10 } 11 12 // 烧水 13 private void boilWater() { 14 System.out.println("烧水..."); 15 } 16 17 // 冲泡咖啡 18 protected abstract void brewCoffee(); 19 20 // 倒入杯中 21 private void pourInCup() { 22 System.out.println("倒入杯中..."); 23 } 24 25 // 加入调料 26 protected abstract void addCondiments(); 27 } 28 29 // 具体模板 - 拿铁咖啡 30 public class LatteCoffeeMaker extends CoffeeMaker { 31 @Override 32 protected void brewCoffee() { 33 System.out.println("冲泡浓缩咖啡..."); 34 } 35 36 @Override 37 protected void addCondiments() { 38 System.out.println("加入牛奶和糖..."); 39 } 40 } 41 42 // 具体模板 - 美式咖啡 43 public class AmericanoCoffeeMaker extends CoffeeMaker { 44 @Override 45 protected void brewCoffee() { 46 System.out.println("冲泡黑咖啡..."); 47 } 48 49 @Override 50 protected void addCondiments() { 51 // 不加入调料 52 } 53 } 54 55 // 客户端代码 56 public class Client { 57 public static void main(String[] args) { 58 CoffeeMaker latteCoffeeMaker = new LatteCoffeeMaker(); 59 latteCoffeeMaker.makeCoffee(); // 制作拿铁咖 60 // 输出结果: 61 // 烧水... 62 // 冲泡浓缩咖啡... 63 // 倒入杯中... 64 // 加入牛奶和糖... 65 // 咖啡制作完成! 66 67 CoffeeMaker americanoCoffeeMaker = new AmericanoCoffeeMaker(); 68 americanoCoffeeMaker.makeCoffee(); // 制作美式咖啡 69 70 // 输出结果: 71 // 烧水... 72 // 冲泡黑咖啡... 73 // 倒入杯中... 74 // 咖啡制作完成! 75 } 76 }
备忘录模式(Memento Pattern)
备忘录模式(Memento Pattern)是一种行为型设计模式,它用于在不破坏封装性的前提下保存和恢复对象的内部状态。备忘录模式通过将对象的状态保存到备忘录对象中,从而允许在后续的时刻将对象恢复到之前保存的状态。
备忘录模式的核心角色包括三个:
- 发起人(Originator):负责创建一个备忘录对象,并可以使用备忘录对象来恢复自己的状态。
- 备忘录(Memento):负责存储发起人的状态,并可以提供发起人访问和恢复状态的接口。
- 管理者(Caretaker):负责管理备忘录对象,可以将备忘录对象保存起来或者从中恢复状态。
备忘录模式的核心思想是将对象的状态进行备份,并通过备忘录对象来保存状态。这样可以在需要的时候将对象的状态恢复到之前的某个状态,从而实现对象状态的撤销或者回滚功能。
一个常见的备忘录模式的例子是文本编辑器的撤销/恢复功能。在一个文本编辑器中,用户可以进行文本的编辑、删除、插入等操作,同时可以通过撤销/恢复按钮来撤销上一步或者恢复之前撤销的操作。这就涉及到了对象状态的保存和恢复,可以通过备忘录模式来实现。

1 // 备忘录类,保存文本编辑器的状态 2 class TextEditorMemento { 3 private String text; 4 5 public TextEditorMemento(String text) { 6 this.text = text; 7 } 8 9 public String getText() { 10 return text; 11 } 12 } 13 14 // 发起人类,文本编辑器类 15 class TextEditor { 16 private String text; 17 18 public void setText(String text) { 19 this.text = text; 20 } 21 22 public String getText() { 23 return text; 24 } 25 26 // 创建备忘录,保存当前状态 27 public TextEditorMemento createMemento() { 28 return new TextEditorMemento(text); 29 } 30 31 // 恢复状态 32 public void restoreMemento(TextEditorMemento memento) { 33 this.text = memento.getText(); 34 } 35 } 36 37 // 管理者类,负责管理备忘录对象 38 class Caretaker { 39 private TextEditorMemento memento; 40 41 public TextEditorMemento getMemento() { 42 return memento; 43 } 44 45 public void setMemento(TextEditorMemento memento) { 46 this.memento = memento; 47 } 48 } 49 50 // 客户端代码 51 public class Main { 52 public static void main(String[] args) { 53 TextEditor textEditor = new TextEditor(); 54 Caretaker caretaker = new Caretaker(); 55 56 textEditor.setText("Hello, world!"); // 设置初始文本 57 System.out.println("Current Text: " + textEditor.getText()); // 输出当前文本 58 59 caretaker.setMemento(textEditor.createMemento()); // 创建备忘录并保存到管理者对象 60 61 textEditor.setText("Hello, design patterns!"); // 修改文本 62 System.out.println("Modified Text: " + textEditor.getText()); // 输出修改后的文本 63 64 textEditor.restoreMemento(caretaker.getMemento()); // 恢复文本编辑器的状态 65 System.out.println("Restored Text: " + textEditor.getText()); // 输出恢复后的文本 66 } 67 }
访问者模式(Visitor Pattern)
访问者模式(Visitor Pattern)是一种行为型设计模式,用于将算法与数据结构分离,使得可以在不修改数据结构的情况下定义新的操作。访问者模式通过将对数据结构的操作封装到独立的访问者类中,实现了对数据结构的操作与数据结构本身的解耦。
访问者模式中的主要角色包括:
- 抽象访问者(Visitor):定义了访问者的接口,包括了访问者对于各种元素类型的访问方法。具体的访问者类需要实现这些接口,从而可以对元素进行具体的操作。
- 具体访问者(Concrete Visitor):实现了抽象访问者接口,对元素进行具体的操作。
- 抽象元素(Element):定义了元素的接口,包括了接受访问者访问的方法。
- 具体元素(Concrete Element):实现了抽象元素接口,定义了具体的元素类型,并实现了接受访问者访问的方法。
- 对象结构(Object Structure):包含了一组元素对象,并且提供了让访问者访问元素的接口。
访问者模式的核心思想是将对数据结构的操作从数据结构本身中分离出来,使得可以根据需要定义新的操作,而不需要修改数据结构的代码。这种分离可以使得系统更加灵活和可扩展,尤其在需要对数据结构进行多种不同操作的情况下,访问者模式能够有效地管理这些操作。

1 // 抽象元素接口:展品 2 interface Exhibit { 3 void accept(Visitor visitor); 4 } 5 6 // 具体元素类:绘画 7 class Painting implements Exhibit { 8 @Override 9 public void accept(Visitor visitor) { 10 visitor.visitPainting(this); 11 } 12 } 13 14 // 具体元素类:雕塑 15 class Sculpture implements Exhibit { 16 @Override 17 public void accept(Visitor visitor) { 18 visitor.visitSculpture(this); 19 } 20 } 21 22 // 具体元素类:文物 23 class Artifact implements Exhibit { 24 @Override 25 public void accept(Visitor visitor) { 26 visitor.visitArtifact(this); 27 } 28 } 29 30 // 抽象访问者接口:导览员 31 interface Visitor { 32 void visitPainting(Painting painting); 33 void visitSculpture(Sculpture sculpture); 34 void visitArtifact(Artifact artifact); 35 } 36 37 // 具体访问者类:具体导览员 38 class TourGuide implements Visitor { 39 @Override 40 public void visitPainting(Painting painting) { 41 System.out.println("导览员正在介绍绘画:" + painting); 42 } 43 44 @Override 45 public void visitSculpture(Sculpture sculpture) { 46 System.out.println("导览员正在介绍雕塑:" + sculpture); 47 } 48 49 @Override 50 public void visitArtifact(Artifact artifact) { 51 System.out.println("导览员正在介绍文物:" + artifact); 52 } 53 } 54 55 // 对象结构类:展厅 56 class ExhibitionHall { 57 private List<Exhibit> exhibits = new ArrayList<>(); 58 59 // 添加展品 60 public void addExhibit(Exhibit exhibit) { 61 exhibits.add(exhibit); 62 } 63 64 // 移除展品 65 public void removeExhibit(Exhibit exhibit) { 66 exhibits.remove(exhibit); 67 } 68 69 // 接受导览员访问 70 public void accept(Visitor visitor) { 71 for (Exhibit exhibit : exhibits) { 72 exhibit.accept(visitor); 73 } 74 } 75 } 76 77 public class VisitorPatternExample { 78 public static void main(String[] args) { 79 // 创建具体展品对象 80 Painting painting = new Painting(); 81 Sculpture sculpture = new Sculpture(); 82 Artifact artifact = new Artifact(); 83 84 // 创建导览员对象 85 TourGuide tourGuide = new TourGuide(); 86 87 // 创建展厅对象 88 ExhibitionHall exhibitionHall = new ExhibitionHall(); 89 exhibitionHall.addExhibit(painting); 90 exhibitionHall.addExhibit(sculpture); 91 exhibitionHall.addExhibit(artifact); 92 93 // 接受导览员访问 94 exhibitionHall.accept(tourGuide); 95 } 96 }
解释器模式(Interpreter Pattern)
解释器模式包含以下几个角色:
- 抽象表达式(Abstract Expression):定义了一个抽象的解释器接口,包含了解释器的抽象方法,用于对表达式进行解释和执行。
- 终结符表达式(Terminal Expression):实现了抽象表达式接口的终结符表达式类,表示语言中的终结符,不再包含子表达式。
- 非终结符表达式(Non-terminal Expression):实现了抽象表达式接口的非终结符表达式类,表示语言中的非终结符,包含了一个或多个子表达式,并通过解释器对子表达式进行解释和执行。
- 上下文(Context):包含了待解释的语言表达式,通常包含了一些全局信息,供解释器使用。
- 客户端(Client):创建和配置具体的表达式对象,并将上下文传递给解释器进行解释和执行。
解释器模式的基本工作流程如下:
- 客户端创建和配置具体的表达式对象,构建语言表达式的抽象语法树。
- 客户端将上下文传递给解释器。
- 解释器对抽象语法树进行解释和执行,递归地对子表达式进行解释和执行,直到所有的表达式都被解释和执行完毕,得到最终的结果。

1 // 抽象表达式接口 2 interface Expression { 3 boolean interpret(String context); 4 } 5 6 // 终结符表达式实现类 7 class TerminalExpression implements Expression { 8 private String pattern; 9 10 public TerminalExpression(String pattern) { 11 this.pattern = pattern; 12 } 13 14 @Override 15 public boolean interpret(String context) { 16 return context.contains(pattern); 17 } 18 } 19 20 // 非终结符表达式实现类 21 class OrExpression implements Expression { 22 private Expression expression1; 23 private Expression expression2; 24 25 public OrExpression(Expression expression1, Expression expression2) { 26 this.expression1 = expression1; 27 this.expression2 = expression2; 28 } 29 30 @Override 31 public boolean interpret(String context) { 32 return expression1.interpret(context) || expression2.interpret(context); 33 } 34 } 35 36 // 非终结符表达式实现类 37 class AndExpression implements Expression { 38 private Expression expression1; 39 private Expression expression2; 40 41 public AndExpression(Expression expression1, Expression expression2) { 42 this.expression1 = expression1; 43 this.expression2 = expression2; 44 } 45 46 @Override 47 public boolean interpret(String context) { 48 return expression1.interpret(context) && expression2.interpret(context); 49 } 50 } 51 52 // 客户端 53 public class Client { 54 public static void main(String[] args) { 55 // 构建正则表达式的语法树 56 Expression expression1 = new TerminalExpression("apple"); 57 Expression expression2 = new TerminalExpression("banana"); 58 Expression expression3 = new TerminalExpression("cherry"); 59 60 Expression orExpression = new OrExpression(expression1, expression2); // apple or banana 61 Expression andExpression = new AndExpression(orExpression, expression3); // (apple or banana) and cherry 62 63 // 使用解释器进行匹配 64 String input1 = "I like apple and cherry"; 65 String input2 = "I prefer banana"; 66 String input3 = "I love cherry"; 67 String input4 = "I enjoy orange"; 68 69 System.out.println(andExpression.interpret(input1)); // 输出 true 70 System.out.println(andExpression.interpret(input2)); // 输出 false 71 System.out.println(andExpression.interpret(input3)); // 输出 false 72 System.out.println(andExpression.interpret(input4)); // 输出 false 73 } 74 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)