【设计模式】常用的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解析、符号处理引擎等。

(完)

添加新评论