前面一篇文章已经提到了设计模式之创建型模式,以及设计模式之创建型模式,最后我们说一说行为型模式
行为型模式
1. 策略模式
策略模式(Strategy Pattern)是为一种行型设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以互相替换。策略模式可以让算法独立于使用它的客户端而变化,从而提高了灵活性和可维护性。
在策略模式中,通常包含以下角色:
- 环境(Context):持有一个策略对象的引用,负责调用具体的策略算法。
- 抽象策略(Strategy):定义了一个算法的接口,所有具体策略类都要实现这个接口。
- 具体策略(Concrete Strategy):具体的算法实现,实现了抽象策略接口。
// 抽象策略接口
interface SortingStrategy {
void sort(int[] arr);
}
// 具体策略类:冒泡排序
class BubbleSort implements SortingStrategy {
@Override
public void sort(int[] arr) {
// 冒泡排序算法实现
System.out.println("Bubble Sort");
}
}
// 具体策略类:快速排序
class QuickSort implements SortingStrategy {
@Override
public void sort(int[] arr) {
// 快速排序算
法实现 System.out.println("Quick Sort");
}
}
// 环境类
class Sorter {
private SortingStrategy strategy;
public Sorter(SortingStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(SortingStrategy strategy) {
this.strategy = strategy;
}
public void sortArray(int[] arr) {
strategy.sort(arr);
}
}
// Strategy 客户Pattern
public class SortExample {
public static void main(String[] args) {
int[] arr = {5, 2, 8, 1, 4};
SortingStrategy bubbleSort = new BubbleSort();
SortingStrategy quickSort = new QuickSort();
Sorter sorter = new Sorter(bubbleSort);
sorter.sortArray(arr);
sorter.setStrategy(quickSort);
sorter.sortArray(arr);
}
}
示例中,我们定义了两种排序算法:冒泡排序和快速排序作为具体的策略类。SortingStrategy
是抽象策略接口,定义了排序方法的接口。Sorter
是环境类,持有一个具体的排序策略对象,在客户端代码中可以动态切换不同的排序策略。通过策略模式,可以让算法独立于客户端而独立变化。
2. 模板方法模式
模板方法模式(Template Method Pattern)是一种行为设计模式,它定义了一个算法的骨架,将算法中的某些步骤延迟到子类中实现。模板方法模式通过将通用的算法步骤放在父类中,而将特定实现延迟到子类中,从而实现代码复用和减少重复。
在模板方法模式中,通常包含以下角色:
- 抽象模板(Abstract Template):定义了一个算法的骨架,其中包含了算法执行的步骤,有些步骤可以是抽象方法,由子类实现。
- 具体模板(Concrete Template):实现了抽象模板中的抽象方法,完成算法的具体步骤。
- 模板方法(Template Method):定义了算法的具体步骤,包含了对抽象方法的调用。
// 抽象模板类
abstract class AbstractClass {
public void templateMethod() {
step1();
step2();
step3();
}
abstract void step1();
abstract void step2();
void step3() {
.println(" System.outDefault implementation of step3");
}
}
// 具体模板类A
class ConcreteClassA extends AbstractClass {
@Override
void step1() {
System.out.println("ConcreteClassA: Step 1");
}
@Override
void step2() {
System.out.println("ConcreteClassA: Step 2");
}
}
// 具体模板类B
class ConcreteClassB extends AbstractClass {
@Override
void step1() {
System.out.println("ConcreteClassB: Step 1");
}
@Override
void step2() {
System.out.println("ConcreteClassB: Step 2");
}
@Override
void step3() {
System.out.println("ConcreteClassB: Custom implementation of step3");
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
AbstractClass classA = new ConcreteClassA();
classA.templateMethod();
System.out.println("----------");
AbstractClass classB = new ConcreteClassB();
classB.templateMethod();
}
}
示例中,AbstractClass
是抽象模板类,定义了算法的骨架,包含了模板方法 templateMethod
和抽象方法 step1
、step2
、以及具体方法 step3
。ConcreteClassA
和 ConcreteClassB
是具体模板类,分别实现了抽象方法和覆盖了默认的具体方法。通过模板方法模式,可以实现算法骨架的复用,并让子类可以灵活实现算法的特定步骤。
3. 观察者模式
观察者模式(Observer Pattern)是一种为设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新。观察者模式实现了对象之间的松耦合,让主题对象和观察者对象可以独立变化。
在观察者模式中,通常包含以下角色:
- 主题(Subject):也称为被观察者,维护一组观察者对象,提供注册和删除观察者的方法,以及通知观察者的方法。
- 观察者(Observer):定义了一个更新接口,用于接收主题的通知并进行相应的更新操作。
- 具体主题(Concrete Subject):实现了主题接口,维护状态变化并在状态变化时通知观察者。
- 具体观察者(Concrete Observer):实现了观察者接口,当接收到主题的通知时会执行相应的更新操作。
import java.util.ArrayList;
import java.util.List;
// 观察者接口
interface Observer {
void update(String message);
}
// 主题接口
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具体观察者类
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received message: " + message);
}
}
// 具体主题类
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update("New message from the subject");
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserver observer1 = new ConcreteObserver("Observer1");
ConcreteObserver observer2 = new ConcreteObserver("Observer2");
subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.notifyObservers();
subject.removeObserver(observer2);
subject.notifyObservers();
}
}
示例中,ConcreteSubject 是具体主题类,维护了一个观察者列表,并在状态变化时通知观察者。ConcreteObserver 是具体观察者类,实现了更新方法。客户端代码中创建了具体主题和观察者对象,注册观察者并通知观察者。观察者模式可以实现对象之间的松耦合,让主题和观察者可以独立变化。
4. 迭代器模式
迭代器模式(Iterator Pattern)是一种行为型设计模式,提供了一种顺序访问集合对象元素的方法,而又不暴露集合的内部表示。迭代器模式让客户端可以访问集合对象的元素,而不需要了解集合的内部结构。
在迭代器模式中,通常包含以下角色:
- 迭代器(Iterator):定义了访问和遍历元素的接口。
- 具体迭代器(Concrete Iterator):实现了迭代器接口,负责对集合进行遍历。
- 聚合对象(Aggregate):定义了创建迭代器的接口。
- 具体聚合对象(Concrete Aggregate):实现了聚合对象接口,返回一个具体的迭代器。
import java.util.ArrayList;
import java.util.List;
// 迭代器接口
interface Iterator {
boolean hasNext();
Object next();
}
// 聚合接口
interface Aggregate {
Iterator createIterator();
}
// 具体迭代器
class ConcreteIterator implements Iterator {
private List<Object> elements;
private int position = 0;
public ConcreteIterator(List<Object> elements) {
this.elements = elements;
}
@Override
public boolean hasNext() {
return position < elements.size();
}
@Override
public Object next() {
Object element = elements.get(position);
position++;
return element;
}
}
// 具体聚合对象
class ConcreteAggregate implements Aggregate {
private List<Object> elements = new ArrayList<>();
public void addElement(Object element) {
elements.add(element);
}
@Override
public Iterator createIterator() {
return new ConcreteIterator(elements);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ConcreteAggregate aggregate = new ConcreteAggregate();
aggregate.addElement("Element 1");
aggregate.addElement("Element 2");
aggregate.addElement("Element 3");
Iterator iterator = aggregate.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
示例中,Iterator
是迭代器接口,定义了访问和遍历元素的方法。ConcreteIterator
是具体迭代器类,实现了迭代器接口,负责对集合进行遍历。Aggregate
是聚合接口,定义了创建迭代器的方法。ConcreteAggregate
是具体聚合类,实现了聚合接口,返回一个具体的迭代器。通过迭代器模式,客户端可以访问集合对象的元素,而不需要了解集合的内部结构。
5. 责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象在链式结构中处理请求,而不需要明确指定接收请求的对象。责任链模式将请求沿着处理链传递,直到有一个对象能够处理请求为止。
在责任链模式中,通常包含以下角色:
- 抽象处理者(Handler):定义了一个处理请求的接口,通常包含一个指向下一个处理者的引用。
- 具体处理者(Concrete Handler):实现了抽象处理者接口,负责处理请求,并决定是否将请求传递给下一个处理者。
// 抽象abstract处理者
class protected Handler {
Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(int request);
}
// 具体处理者A
class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(int request) {
if (request < 10) {
System.out.println("ConcreteHandlerA handles the request: " + request);
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
// 具体处理者B
class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(int request) {
if (request >= 10 && request < 20) {
System.out.println("ConcreteHandlerB handles the request: " + request);
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setSuccessor(handlerB);
handlerA.handleRequest(5);
handlerA.handleRequest(15);
handlerA.handleRequest(25);
}
}
示例中,抽象处理者 Handler 定义了处理请求的接口,并包含一个指向下一个处理者的引用。具体处理者 ConcreteHandlerA 和 ConcreteHandlerB 分别实现了抽象处理者接口,根据条件判断是否处理请求或者将请求传递给下一个处理者。客户端代码中创建了具体处理者对象,并设置了处理链的顺序,然后调用第一个处理者的 handleRequest 方法来处理请求。责任链模式可以动态地调整处理链的顺序,以便灵活地处理请求。
6. 命令模式
请求封装为对象,从而允许参数化客户端操作,并支持将请求排队、记录日志、撤销操作等功能。命令模式将请求发送者和接收者解耦,使得请求发送者不需要知道接收者的具体实现。
在命令模式中,通常包含以下角色:
- 命令接口(Command):声明了执行命令的方法,通常包含一个 execute 方法。
- 具体命令(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.turnOn();
}
}
// 接收者类
class Light {
public void turnOn() {
System.out.println("Light is on");
}
}
// 调用者类
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remoteControl = new RemoteControl();
remoteControl.setCommand(lightOn);
remoteControl.pressButton();
}
}
示例中,Command 是命令接口,定义了执行命令的方法。LightOnCommand 是具体命令类,实现了 Command 接口,负责执行打开灯的命令。Light 是接收者类,负责执行具体的命令操作。RemoteControl 是调用者类,负责设置命令并调用命令来执行请求。通过命令模式,调用者和接收者解耦,支持命令的排队、记录和撤销操作。
7. 状态模式
状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为。在状态模式中,对象的行为取决于其内部状态,而不是取决于方法调用。
在状态模式中,通常包含以下几个角色:
- Context(环境):定义客户端感兴趣的接口,维护一个具体状态的实例,并将请求委托给当前状态对象来处理。
- State(状态接口):定义一个接口,封装与Context的一个特定状态相关的行为。
- ConcreteState(具体状态):每个具体状态实现State接口,提供与该状态相关的行为。
// State接口
interface State {
void handleRequest();
}
// ConcreteState实现
class StateA implements State {
@Override
public void handleRequest() {
System.out.println("Handling request in State A");
}
}
class StateB implements State {
@Override
public void handleRequest() {
System.out.println("Handling request in State B");
}
}
// Context类
class Context {
private State currentState;
public Context() {
currentState = new StateA(); // 初始状态为StateA
}
public void setState(State state) {
currentState = state;
}
public void request() {
currentState.handleRequest();
}
}
// 测试
public class StatePatternDemo {
public static void main(String[] args) {
Context context = new Context();
context.request(); // 输出Handling request in State A
context.setState(new StateB());
context.request(); // 输出Handling request in State B
}
}
通过状态模式,我们可以将对象的行为与其状态分离,使得对象的行为更加灵活和可维护。
8. 访问者模式
访问者模式是一种行为设计模式,它允许你在不改变数据结构的前提下定义对数据结构中元素的新操作。访问者模式将数据结构和数据操作分离,使得数据结构可以独立变化而不影响数据操作。
在访问者模式中,通常有以下几个角色:
- Visitor(访问者):定义了对数据结构中每个元素的访问操作,可以根据需要定义多个不同的访问者。
- ConcreteVisitor(具体访问者):实现了Visitor接口中定义的具体访问操作,针对数据结构中的不同元素进行具体操作。
- Element(元素):定义了接受访问者访问的接口,可以是具体的数据结构或对象。
- ConcreteElement(具体元素):实现了Element接口,表示数据结构中的具体元素,通常会有accept方法用于接受访问者的访问。
- ObjectStructure(对象结构):维护一个元素的集合,并提供访问者访问元素的接口。
// Visitor 接口
interface Visitor {
void visit(Element element);
}
// ConcreteVisitor 实现
class ConcreteVisitor implements Visitor {
@Override
public void visit(Element element) {
System.out.println("Visiting " + element.getClass().getSimpleName());
}
}
// Element 接口
interface Element {
void accept(Visitor visitor);
}
// ConcreteElement 实现
class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// ObjectStructure 类
class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void attach(Element element) {
elements.add(element);
}
public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
// 测试
public class VisitorPatternDemo {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new ConcreteElementA());
objectStructure.attach(new ConcreteElementB());
Visitor visitor = new ConcreteVisitor();
objectStructure.accept(visitor);
}
}
通过访问者模式,我们可以在不改变元素数据结构的情况下定义新的操作,从而实现对数据结构的扩展和灵活性。
9. 中介者模式
中介者模式是一种行为设计模式,它允许对象之间通过一个中介者对象来进行通信,而不是直接相互引用。这种模式有助于减少对象之间的耦合,提高系统的可维护性和可扩展性。
在中介者模式中,通常有以下几个角色:
- Mediator(中介者):定义一个接口用于与各个同事对象通信。中介者通常包含一个或多个方法,用于处理各个同事对象之间的通信。
- ConcreteMediator(具体中介者):实现中介者接口,负责协调各个同事对象的行为。
- Colleague(同事):每个具体同事对象都知道中介者对象,并通过中介者对象来通信。
- ConcreteColleague(具体同事):实现同事接口,每个具体同事对象都包含一些自身的行为,同时需要与其他同事对象协作。
// Mediator 接口
interface Mediator {
void sendMessage(String message, Colleague colleague);
}
// ConcreteMediator 实现
class ConcreteMediator implements Mediator {
private Colleague colleague1;
private Colleague colleague2;
public void setColleague1(Colleague colleague1) {
this.colleague1 = colleague1;
}
public void setColleague2(Colleague colleague2) {
this.colleague2 = colleague2;
}
@Override
public void sendMessage(String message, Colleague colleague) {
if (colleague == colleague1) {
colleague2.receiveMessage(message);
} else if (colleague == colleague2) {
colleague1.receiveMessage(message);
}
}
}
// Colleague 接口
interface Colleague {
void sendMessage(String message);
void receiveMessage(String message);
}
// ConcreteColleague 实现
class ConcreteColleague1 implements Colleague {
private Mediator mediator;
public ConcreteColleague1(Mediator mediator) {
this.mediator = mediator;
}
@Override
public void sendMessage(String message) {
mediator.sendMessage(message, this);
}
@Override
public void receiveMessage(String message) {
System.out.println("Colleague 1 received: " + message);
}
}
class ConcreteColleague2 implements Colleague {
private Mediator mediator;
public ConcreteColleague2(Mediator mediator) {
this.mediator = mediator;
}
@Override
public void sendMessage(String message) {
mediator.sendMessage(message, this);
}
@Override
public void receiveMessage(String message) {
System.out.println("Colleague 2 received: " + message);
}
}
// 测试
public class MediatorPatternDemo {
public static void main(String[] args) {
ConcreteMediator mediator = new ConcreteMediator();
ConcreteColleague1 colleague1 = new ConcreteColleague1(mediator);
ConcreteColleague2 colleague2 = new ConcreteColleague2(mediator);
mediator.setColleague1(colleague1);
mediator.setColleague2(colleague2);
colleague1.sendMessage("Hello from Colleague 1");
colleague2.sendMessage("Hi from Colleague 2");
}
}
通过中介者模式,对象之间的通信变得更加简洁和灵活,各对象之间的关系由中介者来管理,从而降低了对象之间的耦合度。
10. 备忘录模式
备忘录模式是一种行为设计模式,它允许在不破坏封装的前提下捕获并恢复对象的内部状态。备忘录模式通常用于需要保存和恢复对象状态的场景,例如撤销操作、历史记录等。
在备忘录模式中,通常包含以下几个角色:
- Originator(原发器):负责创建一个备忘录对象,并可以使用备忘录对象恢复自身状态。
- Memento(备忘录):存储原发器对象的内部状态,可以包含原发器需要保存的状态信息。
- Caretaker(负责人):负责保存备忘录对象,但不处理或检查备忘录的内容。
// Memento 类
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// Originator 类
class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveToMemento() {
return new Memento(state);
}
public void restoreFromMemento(Memento memento) {
state = memento.getState();
}
}
// Caretaker 类
class Caretaker {
private Memento memento;
public void saveMemento(Memento memento) {
this.memento = memento;
}
public Memento getMemento() {
return memento;
}
}
// 测试
public class MementoPatternDemo {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("State 1");
caretaker.saveMemento(originator.saveToMemento());
originator.setState("State 2");
System.out.println("Current state: " + originator.getState());
originator.restoreFromMemento(caretaker.getMemento());
System.out.println("Restored state: " + originator.getState());
}
}
示例中,Originator类代表了包含状态的对象,它可以创建备忘录对象并使用备忘录对象来恢复自身状态。Caretaker类负责保存和获取备忘录对象。通过备忘录模式,我们可以实现对象状态的保存和恢复,从而实现撤销、历史记录等功能。
11.解释器模式
解释器模式是一种行为设计模式,它定义了一种语言文法的表示,并且定义了解释器来解释这种语言中的语句。解释器模式通常用于解释实际问题的特定领域,如编译器、正则表达式等。
在解释器模式中,通常包含以下几个角色:
- AbstractExpression(抽象表达式):声明一个抽象的解释操作,所有具体表达式都要实现这个接口。
- TerminalExpression(终结符表达式):实现了抽象表达式接口,表示语言中的终结符(最小的语法单位)。
- NonterminalExpression(非终结符表达式):实现了抽象表达式接口,表示语言中的非终结符。
- Context(上下文):包含解释器之外的一些全局信息。
// AbstractExpression 接口
interface Expression {
boolean interpret(String context);
}
// TerminalExpression 实现
class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) {
this.data = data;
}
@Override
public boolean interpret(String context) {
return context.contains(data);
}
}
// NonterminalExpression 实现
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 expr1 = new TerminalExpression("hello");
Expression expr2 = new TerminalExpression("world");
Expression orExpr = new OrExpression(expr1, expr2);
System.out.println(orExpr.interpret("hello")); // 输出 true
System.out.println(orExpr.interpret("world")); // 输出 true
System.out.println(orExpr.interpret("hello world")); // 输出 true
System.out.println(orExpr.interpret("foo")); // 输出 false
}
}
示例中,我们定义了一个简单的语言,包含终结符表达式(TerminalExpression)和非终结符表达式(NonterminalExpression),并通过解释器模式来解释这个语言中的语句。