设计模式学习(三)
行为模式
职责链模式(Chain of Responsibility Pattern)
定义
它允许多个对象有机会处理请求,从而避免请求的发送者与接收者之间的耦合。职责链模式将这些对象连成一条链,并沿着这条链传递请求,直到有对象处理它为止。
职责链模式的角色
- 处理器接口(Handler):定义处理请求的接口,通常包含一个方法用于处理请求和一个方法用于设置下一个处理器。
- 具体处理器(Concrete Handler):实现处理器接口,负责处理请求。如果自己不能处理,则将请求传递给下一个处理器。
- 客户端(Client):创建职责链,并向链上的第一个处理器提交请求。
假设我们有一个审批流程,需要多个级别的审批人(如经理、总监、CEO)来处理请求。我们可以使用职责链模式来实现这个流程。
// 处理器接口:审批人
interface Approver {
void setNextApprover(Approver nextApprover);
void processRequest(PurchaseRequest request);
}
// 具体处理器:经理
class Manager implements Approver {
private Approver nextApprover;
@Override
public void setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
}
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() <= 1000) {
System.out.println("Manager approves the request for $" + request.getAmount());
} else if (nextApprover != null) {
nextApprover.processRequest(request);
}
}
}
// 具体处理器:总监
class Director implements Approver {
private Approver nextApprover;
@Override
public void setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
}
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() <= 5000) {
System.out.println("Director approves the request for $" + request.getAmount());
} else if (nextApprover != null) {
nextApprover.processRequest(request);
}
}
}
// 具体处理器:CEO
class CEO implements Approver {
@Override
public void setNextApprover(Approver nextApprover) {
// CEO 是最后一个审批人,没有下一个审批人
}
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() <= 10000) {
System.out.println("CEO approves the request for $" + request.getAmount());
} else {
System.out.println("Request for $" + request.getAmount() + " requires a board meeting.");
}
}
}
// 请求类:采购请求
class PurchaseRequest {
private double amount;
public PurchaseRequest(double amount) {
this.amount = amount;
}
public double getAmount() {
return amount;
}
}
public class ChainOfResponsibilityPatternDemo {
public static void main(String[] args) {
// 创建审批人
Approver manager = new Manager();
Approver director = new Director();
Approver ceo = new CEO();
// 设置职责链
manager.setNextApprover(director);
director.setNextApprover(ceo);
// 创建采购请求
PurchaseRequest request1 = new PurchaseRequest(800);
PurchaseRequest request2 = new PurchaseRequest(4500);
PurchaseRequest request3 = new PurchaseRequest(12000);
// 处理请求
manager.processRequest(request1);
manager.processRequest(request2);
manager.processRequest(request3);
}
}
jdk或者android系统上的应用
- Java 异常处理
Java 的异常处理机制是职责链模式的一个典型应用。当一个异常被抛出时,它会沿着调用栈向上传递,直到找到能够处理该异常的 catch 块。
try {
// 可能会抛出异常的代码
} catch (NullPointerException e) {
System.out.println("Caught NullPointerException");
} catch (Exception e) {
System.out.println("Caught Exception");
}
- Android事件分发机制
Android 的事件分发机制是职责链模式的一个典型应用。当用户触摸屏幕时,触摸事件会从 Activity 传递到 ViewGroup,再传递到具体的 View,直到有 View 处理该事件。
@Override
public boolean onTouchEvent(MotionEvent event) {
// 处理触摸事件
return super.onTouchEvent(event);
}
命令模式(Command Pattern)
定义
它将请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,并支持请求的排队、记录日志、撤销等操作。命令模式的核心思想是将“请求”抽象为一个独立的对象,从而解耦请求的发送者和接收者。
命令模式的角色
- 命令接口(Command):定义执行操作的接口。
- 具体命令(Concrete Command):实现命令接口,封装具体的操作。
- 接收者(Receiver):执行具体操作的对象。
- 调用者(Invoker):持有命令对象,并调用命令的执行方法。
- 客户端(Client):创建命令对象并设置其接收者。
假设我们有一个遥控器,可以控制多种家电(如灯、风扇等)。我们可以使用命令模式来实现遥控器的功能。
// 命令接口
interface Command {
//执行命令
void execute();
}
// 具体命令:开灯
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
// 具体命令:关灯
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
// 具体命令:开风扇
class FanOnCommand implements Command {
private Fan fan;
public FanOnCommand(Fan fan) {
this.fan = fan;
}
@Override
public void execute() {
fan.on();
}
}
// 具体命令:关风扇
class FanOffCommand implements Command {
private Fan fan;
public FanOffCommand(Fan fan) {
this.fan = fan;
}
@Override
public void execute() {
fan.off();
}
}
// 接收者:灯
class Light {
public void on() {
System.out.println("Light is on");
}
public void off() {
System.out.println("Light is off");
}
}
// 接收者:风扇
class Fan {
public void on() {
System.out.println("Fan is on");
}
public void off() {
System.out.println("Fan is off");
}
}
// 调用者:遥控器
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
public class CommandPatternDemo {
public static void main(String[] args) {
// 创建接收者
Light light = new Light();
Fan fan = new Fan();
// 创建具体命令
Command lightOn = new LightOnCommand(light);
Command lightOff = new LightOffCommand(light);
Command fanOn = new FanOnCommand(fan);
Command fanOff = new FanOffCommand(fan);
// 创建调用者
RemoteControl remote = new RemoteControl();
// 控制灯
remote.setCommand(lightOn);
remote.pressButton(); // 输出: Light is on
remote.setCommand(lightOff);
remote.pressButton(); // 输出: Light is off
// 控制风扇
remote.setCommand(fanOn);
remote.pressButton(); // 输出: Fan is on
remote.setCommand(fanOff);
remote.pressButton(); // 输出: Fan is off
}
}
jdk或者android系统上的应用
- Runnable 接口
Java 的 Runnable 接口是命令模式的一个典型应用。Runnable 封装了一个任务,而 Thread 是调用者,负责执行任务。
// 命令接口
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("Task is running");
}
};
// 调用者
Thread thread = new Thread(task);
thread.start();
- Handler 和 Message
在 Android 中,Handler 和 Message 是命令模式的一个典型应用。Message 封装了一个任务,而 Handler 是调用者,负责处理任务。
// 命令接口
Message message = Message.obtain(handler, new Runnable() {
@Override
public void run() {
System.out.println("Message is handled");
}
});
// 调用者
Handler handler = new Handler(Looper.getMainLooper());
handler.sendMessage(message);
解释器模式(Interpreter Pattern)
定义
它定义了一种语言的语法表示,并使用解释器来解释语言中的句子。这种模式通常用于需要解释和执行特定语法规则的场景,例如编译器、正则表达式引擎等。
解释器模式的角色
- 抽象表达式(AbstractExpression):定义解释操作的接口。
- 终结符表达式(TerminalExpression):实现与文法中的终结符相关的解释操作。
- 非终结符表达式(NonterminalExpression):实现与文法中的非终结符相关的解释操作。
- 上下文(Context):包含解释器需要的全局信息。
- 客户端(Client):构建抽象语法树并调用解释操作。
假设我们需要解释简单的数学表达式,例如 1 + 2 - 3。我们可以使用解释器模式来实现这个功能。
//定义抽象接口
interface Expression {
int interpret(Context context);
}
//定义终结符表达式
class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret(Context context) {
return number;
}
}
//定义非终结符表达式
class AddExpression implements Expression {
private Expression left;
private Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) + right.interpret(context);
}
}
class SubtractExpression implements Expression {
private Expression left;
private Expression right;
public SubtractExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) - right.interpret(context);
}
}
//定义上下文
class Context {
// 这里可以包含解释器需要的全局信息
}
public class InterpreterPatternDemo {
public static void main(String[] args) {
Context context = new Context();
// 构建表达式:1 + 2 - 3
Expression expression = new SubtractExpression(
new AddExpression(new NumberExpression(1), new NumberExpression(2)),
new NumberExpression(3)
);
// 解释并输出结果
int result = expression.interpret(context);
System.out.println("Result: " + result); // 输出: Result: 0
}
}
jdk或者android系统上的应用
迭代器模式(Iterator Pattern)
定义
它提供了一种顺序访问聚合对象(如列表、集合等)中元素的方法,而不需要暴露其底层表示。迭代器模式将遍历逻辑从聚合对象中分离出来,使得聚合对象和遍历逻辑可以独立变化。
迭代器模式的角色
- 迭代器接口(Iterator):定义遍历和访问元素的方法。
- 具体迭代器(ConcreteIterator):实现迭代器接口,负责管理当前遍历的位置。
- 聚合接口(Aggregate):定义创建迭代器的方法。
- 具体聚合类(ConcreteAggregate):实现聚合接口,返回一个具体迭代器的实例。
假设我们有一个自定义的集合类 MyCollection,它存储了一组整数。我们希望提供一个迭代器来遍历这个集合中的元素。
- 定义迭代器接口
interface Iterator<T> {
boolean hasNext(); // 检查是否还有下一个元素
T next(); // 返回下一个元素
}
- 定义具体迭代器
class MyCollectionIterator implements Iterator<Integer> {
private int[] collection;
private int position = 0;
public MyCollectionIterator(int[] collection) {
this.collection = collection;
}
@Override
public boolean hasNext() {
return position < collection.length;
}
@Override
public Integer next() {
if (this.hasNext()) {
return collection[position++];
}
throw new IndexOutOfBoundsException("No more elements");
}
}
- 定义聚合接口
interface Aggregate<T> {
Iterator<T> createIterator(); // 创建迭代器
}
- 定义具体聚合类
class MyCollection implements Aggregate<Integer> {
private int[] items;
public MyCollection(int[] items) {
this.items = items;
}
@Override
public Iterator<Integer> createIterator() {
return new MyCollectionIterator(items);
}
}
public class IteratorPatternDemo {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};
MyCollection collection = new MyCollection(numbers);
// 获取迭代器
Iterator<Integer> iterator = collection.createIterator();
// 遍历集合
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
迭代器模式的优缺点
优点:
- 将遍历逻辑与聚合对象分离,符合单一职责原则。
- 提供了一种统一的方式来遍历不同类型的聚合对象。
- 支持多种遍历方式(例如正向遍历、反向遍历)。
缺点:
- 对于简单的集合,使用迭代器可能会增加代码的复杂性。
- 如果集合的结构发生变化,可能需要修改迭代器的实现。
jdk或者android系统上的应用
Java 的集合框架(如 List、Set、Map)已经内置了迭代器模式。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class JavaIteratorExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// 使用 Java 内置的迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
中介者模式(Mediator Pattern)
定义
它通过引入一个中介者对象来封装一组对象之间的交互。中介者模式减少了对象之间的直接依赖,使得对象之间的耦合度降低,从而更容易维护和扩展。
迭代器模式的角色
- 中介者接口(Mediator):定义对象之间通信的接口。
- 具体中介者(ConcreteMediator):实现中介者接口,协调各个对象之间的交互。
- 同事类(Colleague):定义各个对象的接口,每个同事类都知道中介者对象。
- 具体同事类(ConcreteColleague):实现同事类接口,负责与其他同事类通信。
假设我们有一个聊天室系统,多个用户可以通过聊天室发送消息。聊天室作为中介者,负责将消息从一个用户传递给其他用户。
- 定义中介者接口
interface ChatMediator {
void sendMessage(String message, User user); // 发送消息
void addUser(User user); // 添加用户
}
- 定义具体中介者
class ChatRoom implements ChatMediator {
private List<User> users;
public ChatRoom() {
this.users = new ArrayList<>();
}
@Override
public void sendMessage(String message, User user) {
for (User u : users) {
// 不将消息发送给自己
if (u != user) {
u.receive(message);
}
}
}
@Override
public void addUser(User user) {
this.users.add(user);
}
}
- 定义同事类
abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public abstract void send(String message); // 发送消息
public abstract void receive(String message); // 接收消息
}
- 定义具体同事类
class ChatUser extends User {
public ChatUser(ChatMediator mediator, String name) {
super(mediator, name);
}
@Override
public void send(String message) {
System.out.println(this.name + " 发送消息: " + message);
mediator.sendMessage(message, this);
}
@Override
public void receive(String message) {
System.out.println(this.name + " 收到消息: " + message);
}
}
- 客户端代码
public class MediatorPatternDemo {
public static void main(String[] args) {
// 创建中介者(聊天室)
ChatMediator chatRoom = new ChatRoom();
// 创建用户
User user1 = new ChatUser(chatRoom, "Hehe");
User user2 = new ChatUser(chatRoom, "Bob");
User user3 = new ChatUser(chatRoom, "Charlie");
// 将用户添加到聊天室
chatRoom.addUser(user1);
chatRoom.addUser(user2);
chatRoom.addUser(user3);
// 用户发送消息
user1.send("大家好!");
user2.send("你好,Hehe!");
user3.send("欢迎来到聊天室!");
}
}
备忘录模式(Memento Design Pattern)
定义
它允许在不暴露对象实现细节的情况下保存和恢复对象的状态。该模式主要用于实现撤销(undo)操作。
备忘录模式的角色
- 发起人(Originator):创建并恢复备忘录的对象。
- 备忘录(Memento):存储发起人内部状态的快照,并防止其他对象访问备忘录。备忘录通常只有发起人可以访问其内容。
- 负责人(Caretaker):负责管理备忘录,但不能查看或修改备忘录的内容。
使用备忘录模式来实现一个文本编辑器的撤销功能。
- 发起人(Originator)
public class TextEditor {
private String content;
public TextEditor(String content) {
this.content = content;
}
public void type(String words) {
content += words;
}
// 创建备忘录
public Memento saveStateToMemento() {
return new Memento(content);
}
// 从备忘录恢复状态
public void getStateFromMemento(Memento memento) {
this.content = memento.getContent();
}
public String getContent() {
return content;
}
}
- 备忘录(Memento)
public class Memento {
private String content;
// 私有构造函数,防止外部实例化
private Memento(String content) {
this.content = content;
}
public Memento(TextEditor originator) {
this.content = originator.getContent();
}
public String getContent() {
return content;
}
}
- 负责人(Caretaker)
import java.util.ArrayList;
import java.util.List;
public 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);
}
}
public class Client {
public static void main(String[] args) {
TextEditor editor = new TextEditor("Hello");
Caretaker caretaker = new Caretaker();
editor.type(" world");
caretaker.add(editor.saveStateToMemento());
editor.type("!!!");
System.out.println("Current Content: " + editor.getContent()); // Hello world!!!
// 撤销到上一个状态
editor.getStateFromMemento(caretaker.get(0));
System.out.println("After Undo: " + editor.getContent()); // Hello world
}
}