设计模式-行为型

[1. 责任链(Chain Of Responsibility)]
[2. 命令(Command)]
[3. 解释器(Interpreter)]
[4. 迭代器(Iterator)]
[5. 中介者(Mediator)]
[6. 备忘录(Memento)]
[7. 观察者(Observer)]
[8. 状态(State)]
[9. 策略(Strategy)]
[10. 模板方法(Template Method)]
[11. 访问者(Visitor)]
[12. 空对象(Null)]

1. 责任链(Chain Of Responsibility)

责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。
这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。
如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

主要解决:
职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,
无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

1. 创建抽象的记录器类。

/**
 * Created by zhxh on 2020-02-03.
 * 1. 创建抽象的记录器类。
 */
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 message) {
        if (this.level <= level) {
            write(message);
        }
        // 递归效果,不断调用下一级 logMessage
        if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }

    protected abstract void write(String message);
}

2. 创建扩展了该记录器类的实体类。

/**
 * Created by zhxh on 2020-02-03.
 * 2. 创建扩展了该记录器类的实体类。
 */
public class ConsoleLogger extends AbstractLogger {

    public ConsoleLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        Log.e("---", "Console::Logger  " + message);
    }
}
/**
 * Created by zhxh on 2020-02-03.
 */
public class FileLogger extends AbstractLogger {

    public FileLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        Log.e("---", "File::Logger  " + message);
    }
}

/**
 * Created by zhxh on 2020-02-03.
 */
public class ErrorLogger extends AbstractLogger {

    public ErrorLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        Log.e("---", "Error::Logger  " + message);
    }
}

3. 场景类。

public class App {
    public static void main(String[] args) {
        final AbstractLogger logger = getChainOfLoggers();
        logger.logMessage(AbstractLogger.INFO, "INFO级别信息");
        logger.logMessage(AbstractLogger.DEBUG, "DEBUG级别信息");
        logger.logMessage(AbstractLogger.ERROR, "ERROR级别信息");
    }

    public static AbstractLogger getChainOfLoggers() {
        ErrorLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
        FileLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
        ConsoleLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
        errorLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(consoleLogger);
        return errorLogger;
    }
}

2. 命令(Command)

1. Command类。

/**
 * Created by zhxh on 2019/4/15
 */
public abstract class Command {
    //每个类都必须有个执行命令的方法
    public abstract void execute();
}

/**
 * Created by zhxh on 2019/4/15
 */
public class ConcreteCommand1 extends Command {
    private Receiver receiver;

    public ConcreteCommand1(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        this.receiver.doSomething();
    }
}

2. Receiver类。

/**
 * Created by zhxh on 2019/4/15
 */
public abstract class Receiver {
    public abstract void doSomething();
}
/**
 * Created by zhxh on 2019/4/15
 */
public class ConcreteReceiver1 extends Receiver {
    @Override
    public void doSomething() {
        System.out.println("ConcreteReceiver1--》doSomething");
    }
}

3. Invoker类。

/**
 * Created by zhxh on 2019/4/15
 */
public class Invoker {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void action() {
        this.command.execute();
    }
}

4. 场景类。

/**
 * Created by zhxh on 2019/4/15
 */
public class Client {
    public static void main(String[] args) {
        //声明调用者invoker
        Invoker invoker = new Invoker();
//        定义接收者
        Receiver receiver1 = new ConcreteReceiver1();
        Receiver receiver2 = new ConcreteReceiver2();
//        定义一个发送给接收者的命令
        Command command1 = new ConcreteCommand1(receiver1);
        Command command2 = new ConcreteCommand2(receiver2);
        Command command3 = new ConcreteCommand1(receiver2);
//        把命令交给调用者去执行
        invoker.setCommand(command1);
        invoker.action();
        invoker.setCommand(command2);
        invoker.action();
        invoker.setCommand(command3);
        invoker.action();
    }
}

3. 解释器(Interpreter)

解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。
这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

主要解决:对于一些固定文法构建一个解释句子的解释器。

1. 创建一个表达式接口。

/**
 * Created by zhxh on 2020-02-02.
 * 1. 创建一个表达式接口。
 */
public interface Expression {
    public boolean interpreter(String content);
}

2. 创建实现了上述接口的实体类。

/**
 * Created by zhxh on 2020-02-02.
 * 2. 创建实现了上述接口的实体类。
 */
public class AndExpression implements Expression {

    private Expression expression1;
    private Expression expression2;

    public AndExpression(Expression expression1, Expression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }

    @Override
    public boolean interpreter(String content) {
        return expression1.interpreter(content) && expression2.interpreter(content);
    }
}

3. 场景类。

/*
 * 解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。
 * 这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
 * <p>
 * 主要解决:对于一些固定文法构建一个解释句子的解释器。
 */
public class App {
    public static void main(String[] args) {
        // 3. InterpreterPatternDemo 使用 Expression 类来创建规则,并解析它们
        Expression maleExpression = getMaleExpression();
        // zhxh is male: true
        Log.e("---", "zhxh is male: " + maleExpression.interpreter("zhxh"));

        Expression womanExpression = getMarriedWomanExpression();
        // Julie is married woman: true
        Log.e("---", "Julie is married woman: " + womanExpression.interpreter("Married Julie"));
    }


    /**
     * 规则:zhxh 和 michael 是男性
     */
    public static Expression getMaleExpression() {
        TerminalExpression zhxh = new TerminalExpression("zhxh");
        TerminalExpression michael = new TerminalExpression("michael");
        return new OrExpression(zhxh, michael);
    }

    /**
     * 规则:Julie 是一个已婚的女性
     */
    public static Expression getMarriedWomanExpression() {
        TerminalExpression julie = new TerminalExpression("Julie");
        TerminalExpression married = new TerminalExpression("Married");
        return new AndExpression(julie, married);
    }
}

4. 迭代器(Iterator)

迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。
这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。

主要解决:不同的方式来遍历整个整合对象。

1. 场景类。

/*
迭代器模式
目前已经是一个没落的模式
 * 迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。
 * 这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
 * <p>
 * 主要解决:不同的方式来遍历整个整合对象。
 */
public class App {
    public static void main(String[] args) {
        //3. 使用 NameRepository 来获取迭代器,并打印名字。
        NameRepository nameRepository = new NameRepository();
        for (Iterator iterator = nameRepository.getIterator(); iterator.hasNext(); ) {
            String name = (String) iterator.next();
            Log.e("---", name);
        }
    }
}

5. 中介者(Mediator)

中介者模式也叫做调停者模式,一个对象要和N多个对象交流,就像对象间的战争,很混乱。
这时,加入一个中心,所有的类都和中心交流,中心说怎么处理就怎么处理

例如:机场调度中心(中介者)查看其他飞机(同事类)情况,然后通知飞机降落。

MVC框架,大家都应该使用过Struts,MVC框架,其中的C(Controller)就是一个中介者,叫做前端控制器(Front Controller),
它的作用就是把M(Model,业务逻辑)和V(View,视图)隔离开,协调M和V协同工作,把M运行的结果和V代表的视图融合成一个前端可以展示的页面,,减少
M和V的依赖关系。

1. 创建中介类

/**
 * 1. 创建中介类。
 *
 */
public class CharRoom {
    public static void showMessage(User user, String message) {
        Log.e("---", new Date().toString()
                + " [" + user.getName() + "] : " + message);
    }
}

2. 创建 user 类

/**
 * 2. 创建 user 类。
 */
public class User {
    private String name;

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void sendMessage(String message) {
        CharRoom.showMessage(this, message);
    }
}

3. 场景类。

public class App {
    public static void main(String[] args) {
        User user1 = new User("aa");
        User user2 = new User("bb");
        CharRoom.showMessage(user1, "11");
        CharRoom.showMessage(user2, "22");
    }
}

6. 备忘录(Memento)

备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。

主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,
并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。

1. 创建 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;
    }
}

2. 创建 Originator 类。发件人/发起人

public class Originator {

    private String state;

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public Memento setSateToMemento() {
        return new Memento(state);
    }

    public String getStateFromMemento(Memento memento) {
        return memento.getState();
    }
}

3. 创建 CareTaker 类。 管理员

public class CareTaker {

    private List<Memento> mementoList = new ArrayList<Memento>();

    public void add(Memento memento) {
        mementoList.add(memento);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}

4. 场景类

public class App {
    public static void main(String[] args) {
        // 管理者
        CareTaker careTaker = new CareTaker();

        Originator originator = new Originator();
        originator.setState("State #1");
        originator.setState("State #2");

        // 保存状态
        careTaker.add(originator.setSateToMemento());

        originator.setState("State #3");

        // 保存状态
        careTaker.add(originator.setSateToMemento());

        originator.setState("State #4");

        Log.e("---", "Current State: " + originator.getState());
        // 得到保存的状态
        String fromMemento1 = originator.getStateFromMemento(careTaker.get(0));
        Log.e("---", "First Saved State: " + fromMemento1);
        String fromMemento2 = originator.getStateFromMemento(careTaker.get(1));
        Log.e("---", "Second Saved State: " + fromMemento2);

        /*
         * /---: Current State: State #4
         * /---: First Saved State: State #2
         * /---: Second Saved State: State #3
         */
    }
}

7. 观察者(Observer)

1. Observer类。

/**
 * Created by zhxh on 2019/4/9
 */
public interface Observer {
    //update
    void update(String msg);
}

/**
 * Created by zhxh on 2019/4/9
 */
public class ConcreteObserver implements Observer {
    String name;

    public ConcreteObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(String msg) {
        System.out.println(name + " ConcreteObserver-update()-msg: " + msg);
    }
}

2. Observable类。

/**
 * Created by zhxh on 2019/4/9
 */
public abstract class Observable {
    //监听队列
    private Deque<Observer> observers = new LinkedList<>();

    //添加监听者
    public void addObserver(Observer o) {
        this.observers.add(o);
    }

    //删除监听者
    public void removeObserver(Observer o) {
        this.observers.remove(o);
    }

    public void notifyObservers(String msg) {
        for (Observer observer : this.observers) {
            observer.update(msg);
        }
    }
}

/**
 * Created by zhxh on 2019/4/9
 */
public class ConcreteObservable extends Observable {
    public void doSomething(String msg) {
        System.out.println("ConcreteObservable-doSomething()-msg: " + msg);
        super.notifyObservers(msg);
    }
}

3. 场景类。

/**
 * Created by zhxh on 2019/4/9
 */
public class Client {
    public static void main(String[] args) {
        //创建一个被观察者
        ConcreteObservable observable = new ConcreteObservable();
        //创建一个观察者
        Observer observer1 = new ConcreteObserver("aa");
        Observer observer2 = new ConcreteObserver("bb");
        Observer observer3 = new ConcreteObserver("cc");
        //添加观察者
        observable.addObserver(observer1);
        observable.addObserver(observer2);
        observable.addObserver(observer3);
        observable.removeObserver(observer2);
        //发送信息
        observable.doSomething("haha");
    }
}

8. 状态(State)

状态模式
定义:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
定义又开始模糊了,理一下,当对象的内部状态改变时,它的行为跟随状态的改变而改变了,看起来好像重新初始化了一个类似的。
状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象对应的类发生了改变一样。
状态模式的通用类图:
State--抽象状态角色
ConcreteState--具体状态角色
Context-- 环境角色

1. 角色类。

/**
 * Created by zhxh on 2019/4/14
 */
public abstract class State {
    protected Context context;

    public void setContext(Context context) {
        this.context = context;
    }

    public abstract void handle1();

    public abstract void handle2();
}

/**
 * Created by zhxh on 2019/4/14
 */
class ConcreteState1 extends State {
    @Override
    public void handle1() {
        //本状态逻辑
        System.out.println("state1 do");
    }

    @Override
    public void handle2() {
        super.context.setCurrentState(Context.STATE2);
        super.context.handle2();
    }
}

/**
 * Created by zhxh on 2019/4/14
 */
class ConcreteState2 extends State {
    @Override
    public void handle1() {
        super.context.setCurrentState(Context.STATE1);
        super.context.handle1();
    }

    @Override
    public void handle2() {
        System.out.println("state2 do");
    }
}

/**
 * Created by zhxh on 2019/4/14
 */
public class Context {
    public final static State STATE1 = new ConcreteState1();
    public final static State STATE2 = new ConcreteState2();

    private State currentState;

    public State getCurrentState() {
        return currentState;
    }

    public void setCurrentState(State currentState) {
        this.currentState = currentState;
        //切换状态
        this.currentState.setContext(this);
    }

    public void handle1() {
        this.currentState.handle1();
    }

    public void handle2() {
        this.currentState.handle2();
    }
}

2. 场景类。

/**
 * Created by zhxh on 2019/4/14
 */
public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        context.setCurrentState(new ConcreteState1());
        context.handle1();
        context.handle2();
    }
}

9. 策略(Strategy)

策略模式(Strategy Pattern):定义了算法族,分别封装起来,
让它们之间可相互替换,此模式让算法的变化独立于使用算法的客户。

1. 角色类。

/**
 * Created by zhxh on 2019/4/14
 */
public interface Strategy {
    public void doSomething();
}
/**
 * Created by zhxh on 2019/4/14
 */
public class ConcreteStrategy1 implements Strategy {
    @Override
    public void doSomething() {
        System.out.println("ConcreteStrategy1-->doSomething()");
    }
}
/**
 * Created by zhxh on 2019/4/14
 */
public class Context {
    //abstract strategy
    private Strategy strategy;

    //special strategy
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    //method after
    public void doAnything() {
        this.strategy.doSomething();
    }
}

2. 场景类。

/**
 * Created by zhxh on 2019/4/14
 */
public class Client {
    public static void main(String[] args) {
        Strategy strategy1 = new ConcreteStrategy1();
        Strategy strategy2 = new ConcreteStrategy2();

        Context context1 = new Context(strategy1);
        context1.doAnything();

        Context context2 = new Context(strategy2);
        context2.doAnything();
    }
}

10. 模板方法(Template Method)

模板方法模式,仅仅使用了Java的继承机制,但它是一个应用广泛的模式。

1. 角色类。

/**
 * Created by zhxh on 2019/4/7
 */
public abstract class AbstractClass {
    //基本方法
    protected abstract void doSomething();

    //基本方法
    protected abstract void doAnything();

    //模板方法
    public void templateMethod() {
        //调用方法,做一些事情
        this.doAnything();
        this.doSomething();
    }
}
/**
 * Created by zhxh on 2019/4/7
 */
public class ConcreteClass1 extends AbstractClass {
    @Override
    protected void doSomething() {
        System.out.println("ConcreteClass1-->doSomething");
    }

    @Override
    protected void doAnything() {
        System.out.println("ConcreteClass1-->doAnything");
    }
}

2. 场景类。

/**
 * Created by zhxh on 2019/4/7
 */
public class Client {
    public static void main(String[] args) {
        AbstractClass class1 = new ConcreteClass1();
        AbstractClass class2 = new ConcreteClass2();

        //调用模板方法
        class1.templateMethod();
        class2.templateMethod();
    }
}

11. 访问者(Visitor)

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。
通过这种方式,元素的执行算法可以随着访问者改变而改变。
这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

主要解决:稳定的数据结构和易变的操作耦合问题。

1. 场景类。

public class App {
    public static void main(String[] args) {
        //5. 使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分。

        ComputerPart computer = new Computer();
        computer.accept(new ComputerPartDisplayVisitor());
        /*
         *打印:
         *---: Displaying Mouse.
         *---: Displaying Keyboard.
         *---: Displaying Monitor.
         *---: Displaying Computer.
         */
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容