【设计模式】常用的23种设计模式(三)
简介
常用的设计模式分三大类:
创建型模式(Creational Patterns)
结构型模式(Structural Patterns)
行为型模式(Behavioral Patterns)
本章主要来介绍下常用的11种行为型设计模式。
行为型模式(Behavioral Patterns)
行为型模式主要关注对象之间的通信。
共11种:
- 观察者模式(Observer Pattern)
- 策略模式(Strategy Pattern)
- 模板方法模式(Template Pattern)
- 迭代器模式(Iterator Pattern)
- 责任链模式(Chain of Responsibility Pattern)
- 命令模式(Command Pattern)
- 备忘录模式(Memento Pattern)
- 状态模式(State Pattern)
- 访问者模式(Visitor Pattern)
- 中介者模式(Mediator Pattern)
- 解释器模式(Interpreter Pattern)
1、观察者模式(Observer Pattern)
当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
示例:
当Subject状态变更的时候,通知所有观察者。
创建Subject主题类存放观察者及状态:
public class Subject {
private List<Observer> observerList = new ArrayList<>();
private int state;
public void setState(int state) {
this.state = state;
this.notifyAllObservers();
}
public int getState() {
return state;
}
public void add(Observer observer) {
this.observerList.add(observer);
}
public void notifyAllObservers() {
if (!CollectionUtils.isEmpty(observerList)) {
for (Observer observer : observerList) {
observer.update();
}
}
}
}
创建观察者抽象类及子类:
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
public class BinaryObserver extends Observer {
public BinaryObserver(Subject subject) {
this.subject = subject;
}
@Override
public void update() {
System.out.println("二进制值:" + Integer.toBinaryString(subject.getState()));
}
}
public class OctalObserver extends Observer {
public OctalObserver(Subject subject) {
this.subject = subject;
}
@Override
public void update() {
System.out.println("八进制值:" + Integer.toOctalString(subject.getState()));
}
}
public class HexObserver extends Observer {
public HexObserver(Subject subject) {
this.subject = subject;
}
@Override
public void update() {
System.out.println("十六进制值:" + Integer.toHexString(subject.getState()));
}
}
测试类:
public class ObserverTest {
public static void main(String[] args) {
Subject subject = new Subject();
Observer binaryObserver = new BinaryObserver(subject);
Observer hexObserver = new HexObserver(subject);
Observer octalObserver = new OctalObserver(subject);
subject.add(binaryObserver);
subject.add(hexObserver);
subject.add(octalObserver);
System.out.println("设置值=15");
subject.setState(15);
System.out.println("设置值=10");
subject.setState(10);
}
}
输出:
设置值=15
二进制值:1111
十六进制值:f
八进制值:17
设置值=10
二进制值:1010
十六进制值:a
八进制值:12
2、策略模式(Strategy Pattern)
策略模式定义了一系列算法,并将每个算法封装起来,使得他们可以相互替换。一个接口对应多个实现类
优点:算法可自由切换;避免使用多重条件判断;扩展性良好;
缺点:策略类会增多,所有策略类都需要对外暴露;
示例:
策略接口及实现类:
public interface Strategy {
public int executeStrategy(int a, int b);
}
public class AddStrategy implements Strategy {
@Override
public int executeStrategy(int a, int b) {
return a + b;
}
}
public class SubtractStrategy implements Strategy {
@Override
public int executeStrategy(int a, int b) {
return a - b;
}
}
public class MultiplyStrategy implements Strategy {
@Override
public int executeStrategy(int a, int b) {
return a * b;
}
}
创建Context类执行策略:
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int a, int b) {
return strategy.executeStrategy(a, b);
}
}
StrategyTest测试类:
public class StrategyTest {
public static void main(String[] args) {
Context context = new Context(new AddStrategy());
System.out.println("1 + 2 = " + context.executeStrategy(1, 2));
context = new Context(new SubtractStrategy());
System.out.println("5 - 1 = " + context.executeStrategy(5, 1));
context = new Context(new MultiplyStrategy());
System.out.println("1 * 3 = " + context.executeStrategy(1, 3));
}
}
输出:
1 + 2 = 3
5 - 1 = 4
1 * 3 = 3
3、模板方法模式(Template Pattern)
在一个抽象类中公开定义了执行它的方法的方式/模板。它的子类可以按需重写方法实现,但调用将以抽象类中定义的方式进行。
示例:
定义抽象类及其子类:
public abstract class Game {
public void init() {}
public void start() {}
public void end() {}
public final void play() {
init();
start();
end();
}
}
public class BasketballGame extends Game {
@Override
public void init() {
System.out.println("BasketballGame init...");
}
@Override
public void start() {
System.out.println("BasketballGame start...");
}
@Override
public void end() {
System.out.println("BasketballGame end...");
}
}
public class FootballGame extends Game {
@Override
public void init() {
System.out.println("FootballGame init...");
}
@Override
public void start() {
System.out.println("FootballGame start...");
}
@Override
public void end() {
System.out.println("FootballGame end...");
}
}
TemplateTest测试类:
public class TemplateTest {
public static void main(String[] args) {
Game basketballGame = new BasketballGame();
basketballGame.play();
Game footballGame = new FootballGame();
footballGame.play();
}
}
输出:
BasketballGame init...
BasketballGame start...
BasketballGame end...
FootballGame init...
FootballGame start...
FootballGame end...
4、迭代器模式(Iterator Pattern)
这种模式用户顺序访问集合对象的元素,不需要知道集合对象的底层表示。
应用实例:Java中的Iterator
示例:
创建接口:
public interface Container {
public Iterator getIterator();
}
public interface Iterator {
public boolean hasNext();
public String next();
}
创建实现了Container接口的实体类。该类有实现了Iterator接口的内部类NameIterator:
public class NameRepository implements Container {
private String[] names = {"One", "Two", "Three", "Four"};
@Override
public Iterator getIterator() {
return new NameIterator();
}
private class NameIterator implements Iterator {
private int index;
@Override
public boolean hasNext() {
if (index < names.length) {
return true;
}
return false;
}
@Override
public String next() {
if (this.hasNext()) {
return names[index++];
}
return null;
}
}
}
IteratorTest测试类:
public class IteratorTest {
public static void main(String[] args) {
NameRepository nameResponstry = new NameRepository();
for (Iterator iter = nameResponstry.getIterator(); iter.hasNext();) {
System.out.println(iter.next());
}
}
}
输出:
One
Two
Three
Four
5、责任链模式(Chain of Responsibility Pattern)
为请求创建一个接收者对象的链,一个对象不能处理该请求,那么他会把相同的请求传给下一个接收者。
应用实例:
过滤器、拦截器、JS中的事件冒泡
示例:
抽象类及其子类:
public abstract class AbstractLogger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;
protected int level;
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLogger nextLogger) {
this.nextLogger = nextLogger;
}
public void logMessage(int level, String msg) {
if (this.level <= level) {
write(msg);
}
if (nextLogger != null) {
nextLogger.logMessage(level, msg);
}
}
abstract void write(String msg);
}
public class InfoLogger extends AbstractLogger {
public InfoLogger(int level) {
this.level = level;
}
@Override
void write(String msg) {
System.out.println("InfoLogger :" + msg);
}
}
public class DebugLogger extends AbstractLogger {
public DebugLogger(int level) {
this.level = level;
}
@Override
void write(String msg) {
System.out.println("DebugLogger :" + msg);
}
}
public class ErrorLogger extends AbstractLogger {
public ErrorLogger(int level) {
this.level = level;
}
@Override
void write(String msg) {
System.out.println("ErrorLogger :" + msg);
}
}
测试类:
public class ResponsibilityTest {
static AbstractLogger getAbstractLogger() {
InfoLogger infoLogger = new InfoLogger(AbstractLogger.INFO);
DebugLogger debugLogger = new DebugLogger(AbstractLogger.DEBUG);
ErrorLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
errorLogger.setNextLogger(debugLogger);
debugLogger.setNextLogger(infoLogger);
return errorLogger;
}
public static void main(String[] args) {
AbstractLogger abstractLogger = getAbstractLogger();
abstractLogger.logMessage(AbstractLogger.INFO, "1111");
abstractLogger.logMessage(AbstractLogger.DEBUG, "2222");
abstractLogger.logMessage(AbstractLogger.ERROR, "3333");
}
}
输出:
InfoLogger :1111
DebugLogger :2222
InfoLogger :2222
ErrorLogger :3333
DebugLogger :3333
InfoLogger :3333
6、命令模式(Command Pattern)
通过命令的形式将调用者和接受者解耦,同时方便记录、撤销/重做、事务等的处理。
示例:调用者(Control)发送开灯命令(TurnOnLight)给接受者(Light)。
Command命令接口及其实现类:
public interface Command {
public void execute();
public void undo();
}
public class TurnOnLight implements Command {
private Light light;
public TurnOnLight(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOn();
}
@Override
public void undo() {
light.turnOff();
}
}
public class TurnOffLight implements Command {
private Light light;
public TurnOffLight(Light light) {
this.light = light;
}
@Override
public void execute() {
light.turnOff();
}
@Override
public void undo() {
light.turnOn();
}
}
接受者及调用者类:
public class Light {
private String loc;
public Light(String loc) {
this.loc = loc;
}
public void turnOn() {
System.out.println(loc + "-On");
}
public void turnOff() {
System.out.println(loc + "-Off");
}
}
public class Control {
public void commandExecute(Command command) {
command.execute();
}
public void commandUndo(Command command) {
command.undo();
}
}
测试类:
public class CommandTest {
public static void main(String[] args) {
Light light = new Light("灯1");
TurnOnLight turnOnLight = new TurnOnLight(light);
Control control = new Control();
control.commandExecute(turnOnLight);
control.commandUndo(turnOnLight);
}
}
输出:
灯1-On
灯1-Off
7、备忘录模式(Memento Pattern)
保存对象的某个状态,以便在适当的时候恢复对象。
应用实例:打游戏时的存档;数据库的事务管理;IE中的回退;Windows中的ctrl+z撤销;
示例:
Originator创建并在Memento对象中存储状态。Caretaker对象负责从Memento中恢复对象的状态。
创建备忘录Memento类:
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
创建发起者Originator类:
public class Originator {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public Memento addStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
创建备忘录管理者CareTaker类:
public class CareTaker {
List<Memento> mementoList = new ArrayList<>();
public void add(Memento memento) {
mementoList.add(memento);
}
public Memento get(int i) {
return mementoList.get(i);
}
}
测试类:
public class MementoTest {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setState("State #1");
originator.setState("State #2");
careTaker.add(originator.addStateToMemento());
originator.setState("State #3");
careTaker.add(originator.addStateToMemento());
originator.setState("State #4");
System.out.println("Current State:" + originator.getState());
originator.getStateFromMemento(careTaker.get(0));
System.out.println("First Saved State:" + originator.getState());
originator.getStateFromMemento(careTaker.get(1));
System.out.println("Second Saved State:" + originator.getState());
}
}
输出:
Current State:State #4
First Saved State:State #2
Second Saved State:State #3
8、状态模式(State Pattern)
在状态模式中,类的行为是基于它的状态改变的。
9、访问者模式(Visitor Pattern)
访问者模式主要是将数据结构和数据操作分离。
10、中介者模式(Mediator Pattern)
中介者模式主要是通过提供中介类,来降低多个对象和类之间的复杂度。
应用实例:机场调用系统;MVC框架,其中C(控制器)其实就是M(模型)和V(视图)之间的中介者。
11、解释器模式(Interpreter Pattern)
对于一些固定文法构造一个解释器,来解释一个特定的上下文。
这种模式被用在SQL解析、符号处理引擎等。
(完)