23种设计模式归纳总结——行为型

Posted 化作孤岛的瓜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23种设计模式归纳总结——行为型相关的知识,希望对你有一定的参考价值。

主要解决的就是“类或对象之间的交互”问题,将不同的行为代码解耦

目录

12.观察者模式

13.模板模式

14.策略模式

15.责任链模式

16.状态模式

17.迭代器模式

18.访问者模式

19.备忘录模式

20.命令模式

21.解释器模式

22.中介模式

12.观察者模式

概念:
在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知
区别:
观察者模式是一对多,生产者消费者是多对多
示例:
目标类负责实现对观察者的增删与通知,观察者负责接受通知。

static class Message 
        public int code;
        public Object msg;
    

    /**
     * 抽象目标类,提供增加,删除,通知观察者对象的抽象方法
     */
    interface Subject 
        void registerObserver(Observer observer);

        void removeObserver(Observer observer);

        void notifyObservers(Message message);
    

    /**
     * 具体目标类,抽象目标类中的方法,通过集合保存观察者
     */
    static class ConcreteSubject implements Subject 
        private List<Observer> observers = new ArrayList<Observer>();

        @Override
        public void registerObserver(Observer observer) 
            observers.add(observer);
        

        @Override
        public void removeObserver(Observer observer) 
            observers.remove(observer);
        

        @Override
        public void notifyObservers(Message message) 
            for (Observer observer : observers) 
                observer.update(message);
            
        
    

    /**
     * 抽象观察者,包含一个更新自己的抽象方法
     */
    interface Observer 
        void update(Message message);
    

    /**
     * 具体观察者,实现抽象观察者中的抽象更新方法
     */
    static class ConcreteObserverOne implements Observer 
        @Override
        public void update(Message message) 
            //TODO: 获取消息通知,执行自己的逻辑...
            System.out.println("ConcreteObserverOne is notified.");
        
    

    static class ConcreteObserverTwo implements Observer 
        @Override
        public void update(Message message) 
            //TODO: 获取消息通知,执行自己的逻辑...
            System.out.println("ConcreteObserverTwo is notified.");
        
    

    public static void main(String[] args) 
        ConcreteSubject subject = new ConcreteSubject();
        subject.registerObserver(new ConcreteObserverOne());
        subject.registerObserver(new ConcreteObserverTwo());
        subject.notifyObservers(new Message());
    

13.模板模式

概念:
全称是模板方法设计模式,在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现
简单的说就是通过抽象方法让子类继承去实现部分逻辑
模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤
模板模式有两大作用:复用和扩展
示例:
绘制一个画布,需要分别绘制背景层与内容层

static abstract class AbsCanvas 

        public final void draw() 
            drawBg();
            drawContent();
        

        protected abstract void drawBg();

        protected abstract void drawContent();
    

    static class CircleCanvas extends AbsCanvas 

        @Override
        protected void drawBg() 
            System.out.println("绘制圆形背景");
        

        @Override
        protected void drawContent() 
            System.out.println("绘制圆形内容");
        
    

    static class SquareCanvas extends AbsCanvas 

        @Override
        protected void drawBg() 
            System.out.println("绘制方形背景");
        

        @Override
        protected void drawContent() 
            System.out.println("绘制方形内容");
        
    

    public static void main(String[] args) 
        AbsCanvas circleCanvas = new CircleCanvas();
        AbsCanvas squareCanvas = new SquareCanvas();
        circleCanvas.draw();
        squareCanvas.draw();
    

14.策略模式

概念:
定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。
使算法的变化独立于使用算法的代码。
示例:
有普通订单和团购订单两种,分别对应不同降价计算规则,需要在拿到订单时自动根据降价策略计算价格。

/**
     * 订单
     */
    static class Order 
        public OrderType mOrderType;
        public double price;

        public Order(final OrderType orderType, final double price) 
            mOrderType = orderType;
            this.price = price;
        
    

    /**
     * 订单类型
     */
    enum OrderType 
        NORMAL, GROUPON,
    

    /**
     * 策略的定义,降价策略
     */
    public interface DiscountStrategy 
        double calDiscount(Order order);
    

    /**
     * 普通降价策略
     */
    static class NormalDiscountStrategy implements DiscountStrategy 
        @Override
        public double calDiscount(final Order order) 
            return order.price * 1.0d;
        
    

    /**
     * 团购降价策略
     */
    static class GrouponDiscountStrategy implements DiscountStrategy 
        @Override
        public double calDiscount(final Order order) 
            return order.price * 0.8d;
        
    

    // 策略的创建
    static class DiscountStrategyFactory 
        private static final Map<OrderType, DiscountStrategy> strategies = new HashMap<>();

        static 
            strategies.put(OrderType.NORMAL, new NormalDiscountStrategy());
            strategies.put(OrderType.GROUPON, new GrouponDiscountStrategy());
        

        public static DiscountStrategy getDiscountStrategy(OrderType type) 
            return strategies.get(type);
        
    

    // 策略的使用,订单管理
    static class OrderService 
        public double discount(Order order) 
            OrderType type = order.mOrderType;
            DiscountStrategy discountStrategy = DiscountStrategyFactory.getDiscountStrategy(type);
            return discountStrategy.calDiscount(order);
        
    

    public static void main(String[] args) 
        OrderService orderService = new OrderService();
        System.out.println("普通价格:" + orderService.discount(new Order(OrderType.NORMAL, 100d)));
        System.out.println("团购价格:" + orderService.discount(new Order(OrderType.GROUPON, 100d)));
    

15.责任链模式

概念:
多个处理器依次处理同一个请求。
一个请求先经过A处理器处理,然后再把请求传递给B处理器,B处理器处理完后再传递给C处理器,
以此类推,形成一个链条。链条上的每个处理器各自承担各自的处理职责,所以叫作责任链模式。
示例:
敏感词过滤器,包括广告过滤,色情过滤

//过滤器
    public interface SensitiveWordFilter 
        boolean doFilter(String content);
    

    //色情过滤
    static class SexyWordFilter implements SensitiveWordFilter 
        @Override
        public boolean doFilter(String content) 
            boolean legal = true;
            //...
            return legal;
        
    

    //广告过滤
    static class AdsWordFilter implements SensitiveWordFilter 

        @Override
        public boolean doFilter(final String content) 
            boolean legal = true;
            //...
            return legal;
        
    

    /**
     * 过滤器责任链
     */
    static class SensitiveWordFilterChain 
        private List<SensitiveWordFilter> filters = new ArrayList<>();

        public void addFilter(SensitiveWordFilter filter) 
            this.filters.add(filter);
        

        // return true if content doesn't contain sensitive words.
        public boolean filter(String content) 
            for (SensitiveWordFilter filter : filters) 
                if (!filter.doFilter(content)) 
                    return false;
                
            
            return true;
        
    

    public static void main(String[] args) 
        SensitiveWordFilterChain filterChain = new SensitiveWordFilterChain();
        filterChain.addFilter(new AdsWordFilter());
        filterChain.addFilter(new SexyWordFilter());

        boolean legal = filterChain.filter("一条评论");
        if (!legal) 
            // 不发表
            System.out.println("过滤");
         else 
            // 发表
            System.out.println("合格");
        
    

16.状态模式

概念:
通过分支逻辑或者查表法实现状态的管理
一般用来实现状态机,而状态机常用在游戏、工作流引擎等系统开发中
示例:
马里奥形态的转变就是一个状态机。其中,马里奥的不同形态就是状态机中的“状态”,
游戏情节(比如吃了蘑菇)就是状态机中的“事件”,
加减积分就是状态机中的“动作”。比如,吃蘑菇这个事件,
会触发状态的转移:从小马里奥转移到超级马里奥,以及触发动作的执行(增加100积分)。
1.分支逻辑法:
分支逻辑法。利用if-else或者switch-case分支逻辑,参照状态转移图,
将每一个状态转移原模原样地直译成代码。对于简单的状态机来说,这种实现方式最简单、最直接,是首选。

public enum State 
        SMALL(0),
        SUPER(1),
        FIRE(2),
        CAPE(3);

        private int value;

        private State(int value) 
            this.value = value;
        

        public int getValue() 
            return this.value;
        
    

    static class MariostateMachine 
        private int score;
        private State currentState;

        public MarioStateMachine() 
            this.score = 0;
            this.currentState = State.SMALL;
        

        public void obtainMushRoom() 
            if (currentState.equals(State.SMALL)) 
                this.currentState = State.SUPER;
                this.score += 100;
            
        

        public void obtainCape() 
            if (currentState.equals(State.SMALL) || currentState.equals(State.SUPER) ) 
                this.currentState = State.CAPE;
                this.score += 200;
            
        

        public void obtainFireFlower() 
            if (currentState.equals(State.SMALL) || currentState.equals(State.SUPER) ) 
                this.currentState = State.FIRE;
                this.score += 300;
            
        

        //遇到怪物
        public void meetMonster() 
            if (currentState.equals(State.SUPER)) 
                this.currentState = State.SMALL;
                this.score -= 100;
                return;
            

            if (currentState.equals(State.CAPE)) 
                this.currentState = State.SMALL;
                this.score -= 200;
                return;
            

            if (currentState.equals(State.FIRE)) 
                this.currentState = State.SMALL;
                this.score -= 300;
                return;
            
        

        public int getScore() 
            return this.score;
        

        public State getCurrentState() 
            return this.currentState;
        
    

    public static void main(String[] args) 
        MarioStateMachine stateMachine = new MarioStateMachine();
    

2.查表法
对于状态很多、状态转移比较复杂的状态机来说,查表法比较合适。通过二维数组来表示状态转移图,
能极大地提高代码的可读性和可维护性。

public enum State 
        SMALL(0),
        SUPER(1),
        FIRE(2),
        CAPE(3);

        private int value;

        private State(int value) 
            this.value = value;
        

        public int getValue() 
            return this.value;
        
    

    public enum Event 
        GOT_MUSHROOM(0),
        GOT_CAPE(1),
        GOT_FIRE(2),
        MET_MONSTER(3);

        private int value;

        private Event(int value) 
            this.value = value;
        

        public int getValue() 
            return this.value;
        
    

    static class MarioStateMachine 
        private int score;
        private State currentState;

        static final State[][] transitionTable = 
          SUPER, CAPE, FIRE, SMALL,
          SUPER, CAPE, FIRE, SMALL,
          CAPE, CAPE, CAPE, SMALL,
          FIRE, FIRE, FIRE, SMALL
        ;

        private static final int[][] actionTable = 
          +100, +200, +300, +0,
          +0, +200, +300, -100,
          +0, +0, +0, -200,
          +0, +0, +0, -300
        ;

        public MarioStateMachine() 
            this.score = 0;
            this.currentState = SMALL;
        

        public void obtainMushRoom() 
            executeEvent(Event.GOT_MUSHROOM);
        

        public void obtainCape() 
            executeEvent(Event.GOT_CAPE);
        

        public void obtainFireFlower() 
            executeEvent(Event.GOT_FIRE);
        

        public void meetMonster() 
            executeEvent(Event.MET_MONSTER);
        

        private void executeEvent(Event event) 
            int stateValue = currentState.getValue();
            int eventValue = event.getValue();
            this.currentState = transitionTable[stateValue][eventValue];
            this.score += actionTable[stateValue][eventValue];
        

        public int getScore() 
            return this.score;
        

        public State getCurrentState() 
            return this.currentState;
        

    

3.状态模式
对于状态并不多、状态转移也比较简单,但事件触发执行的动作包含的业务逻辑可能比较复杂的状态机来说,我们首选这种实现方式。

public enum State 
        SMALL(0),
        SUPER(1),
        FIRE(2);

        private int value;

        private State(int value) 
            this.value = value;
        

        public int getValue() 
            return this.value;
        
    

    public interface IMario  //所有状态类的接口
        State getName();

        //以下是定义的事件
        void obtainMushRoom();

        void obtainFireFlower();

        void meetMonster();
    

    static class SmallMario implements IMario 
        private MarioStateMachine stateMachine;

        public SmallMario(MarioStateMachine stateMachine) 
            this.stateMachine = stateMachine;
        

        @Override
        public State getName() 
            return State.SMALL;
        

        @Override
        public void obtainMushRoom() 
            stateMachine.setCurrentState(new SuperMario(stateMachine));
            stateMachine.setScore(stateMachine.getScore() + 100);
        

        @Override
        public void obtainFireFlower() 
            stateMachine.setCurrentState(new FireMario(stateMachine));
            stateMachine.setScore(stateMachine.getScore() + 300);
        

        @Override
        public void meetMonster() 
            // do nothing...
        
    

    static class FireMario implements IMario 
        private MarioStateMachine stateMachine;

        public FireMario(MarioStateMachine stateMachine) 
            this.stateMachine = stateMachine;
        

        @Override
        public State getName() 
            return State.FIRE;
        

        @Override
        public void obtainMushRoom() 
            stateMachine.setCurrentState(new SuperMario(stateMachine));
            stateMachine.setScore(stateMachine.getScore() + 100);
        

        @Override
        public void obtainFireFlower() 
            stateMachine.setCurrentState(new FireMario(stateMachine));
            stateMachine.setScore(stateMachine.getScore() + 300);
        

        @Override
        public void meetMonster() 
            // do nothing...
        
    

    static class SuperMario implements IMario 
        private MarioStateMachine stateMachine;

        public SuperMario(MarioStateMachine stateMachine) 
            this.stateMachine = stateMachine;
        

        @Override
        public State getName() 
            return State.SUPER;
        

        @Override
        public void obtainMushRoom() 
            // do nothing...
        

        @Override
        public void obtainFireFlower() 
            stateMachine.setCurrentState(new FireMario(stateMachine));
            stateMachine.setScore(stateMachine.getScore() + 300);
        

        @Override
        public void meetMonster() 
            stateMachine.setCurrentState(new SmallMario(stateMachine));
            stateMachine.setScore(stateMachine.getScore() - 100);
        
    


    public class MarioStateMachine 
        private int score;
        private IMario currentState; // 不再使用枚举来表示状态

        public MarioStateMachine() 
            this.score = 0;
            this.currentState = new SmallMario(this);
        

        public void obtainMushRoom() 
            this.currentState.obtainMushRoom();
        

        public void obtainFireFlower() 
            this.currentState.obtainFireFlower();
        

        public void meetMonster() 
            this.currentState.meetMonster();
        

        public int getScore() 
            return this.score;
        

        public State getCurrentState() 
            return this.currentState.getName();
        

        public void setScore(int score) 
            this.score = score;
        

        public void setCurrentState(IMario currentState) 
            this.currentState = currentState;
        
    

17.迭代器模式

概念:
迭代器是用来遍历容器的,所以,一个完整的迭代器模式一般会涉及容器和容器迭代器两部分内容。
为了达到基于接口而非实现编程的目的,容器又包含容器接口、容器实现类,迭代器又包含迭代器接口、迭代器实现类。

public interface Iterator<E> 
        boolean hasNext();
        void next();
        E currentItem();
    

    static class ArrayIterator<E> implements Iterator<E> 
        private int cursor;
        private ArrayList<E> arrayList;

        public ArrayIterator(ArrayList<E> arrayList) 
            this.cursor = 0;
            this.arrayList = arrayList;
        

        @Override
        public boolean hasNext() 
            return cursor != arrayList.size(); //注意这里,cursor在指向最后一个元素的时候,hasNext()仍旧返回true。
        

        @Override
        public void next() 
            cursor++;
        

        @Override
        public E currentItem() 
            if (cursor >= arrayList.size()) 
                throw new NoSuchElementException();
            
            return arrayList.get(cursor);
        
    

    public interface List<E> 
        Iterator iterator();
        //...省略其他接口函数...

        void add(E e);

        int size();

        E get(int index);
    

    static class ArrayList<E> implements List<E> 
        //...
        public Iterator iterator() 
            return new ArrayIterator(this);
        

        @Override
        public void add(final E e) 
            //...
        

        @Override
        public int size() 
            //...
            return 0;
        

        @Override
        public E get(int index) 
            return null;
        
    

    public static void main(String[] args) 
        List<String> names = new ArrayList<>();
        names.add("xzg");
        names.add("wang");
        names.add("zheng");

        Iterator<String> iterator = names.iterator();
        while (iterator.hasNext()) 
            System.out.println(iterator.currentItem());
            iterator.next();
        
    

18.访问者模式

概念:
允许一个或者多个操作应用到一组对象上,解耦操作和对象本身。
示例:
从网站上爬取了很多资源文件,它们的格式有三种:PDF、PPT、Word。我们现在要开发一个工具来处理这批资源文件,
抽取出来放在txt中

static abstract class ResourceFile 
        protected String filePath;

        public ResourceFile(String filePath) 
            this.filePath = filePath;
        

        abstract public void accept(Visitor vistor);
    

    static class PdfFile extends ResourceFile 
        public PdfFile(String filePath) 
            super(filePath);
        

        @Override
        public void accept(Visitor visitor) 
            visitor.visit(this);
        

        //...
    

    static class WordFile extends ResourceFile 
        public WordFile(String filePath) 
            super(filePath);
        

        @Override
        public void accept(Visitor visitor) 
            visitor.visit(this);
        

        //...
    

    static class PPTFile extends ResourceFile 
        public PPTFile(String filePath) 
            super(filePath);
        

        @Override
        public void accept(Visitor visitor) 
            visitor.visit(this);
        

        //...
    

    public interface Visitor 
        void visit(PdfFile pdfFile);

        void visit(PPTFile pdfFile);

        void visit(WordFile pdfFile);
    

    static class Extractor implements Visitor 
        @Override
        public void visit(PPTFile pptFile) 
            //...
            System.out.println("Extract PPT.");
        

        @Override
        public void visit(PdfFile pdfFile) 
            //...
            System.out.println("Extract PDF.");
        

        @Override
        public void visit(WordFile wordFile) 
            //...
            System.out.println("Extract WORD.");
        
    

    static class Compressor implements Visitor 
        @Override
        public void visit(PPTFile pptFile) 
            //...
            System.out.println("Compress PPT.");
        

        @Override
        public void visit(PdfFile pdfFile) 
            //...
            System.out.println("Compress PDF.");
        

        @Override
        public void visit(WordFile wordFile) 
            //...
            System.out.println("Compress WORD.");
        

    


    public static void main(String[] args) 
        Extractor extractor = new Extractor();
        List<ResourceFile> resourceFiles = listAllResourceFiles(args[0]);
        for (ResourceFile resourceFile : resourceFiles) 
            resourceFile.accept(extractor);
        

        Compressor compressor = new Compressor();
        for (ResourceFile resourceFile : resourceFiles) 
            resourceFile.accept(compressor);
        
    

    private static List<ResourceFile> listAllResourceFiles(String resourceDirectory) 
        List<ResourceFile> resourceFiles = new ArrayList<>();
        //...根据后缀(pdf/ppt/word)由工厂方法创建不同的类对象(PdfFile/PPTFile/WordFile)
        resourceFiles.add(new PdfFile("a.pdf"));
        resourceFiles.add(new WordFile("b.word"));
        resourceFiles.add(new PPTFile("c.ppt"));
        return resourceFiles;
    

19.备忘录模式

概念:
不违背封装原则的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后恢复对象为先前的状态。
示例:
希望你编写一个小程序,可以接收命令行的输入。用户输入文本时,程序将其追加存储在内存文本中;用户输入“:list”,
程序在命令行中输出内存文本的内容;用户输入“:undo”,程序会撤销上一次输入的文本,也就是从内存文本中将上次输入的文本删除掉。
解决方案:
定义一个独立的类(Snapshot类)来表示快照(自身不可变),而不是复用InputText类。这个类只暴露get()方法,没有set()等任何修改内部状态的方法。
其二,在InputText类中,我们把setText()方法重命名为restoreSnapshot()方法,用意更加明确,只用来恢复对象。

static class InputText 
        private StringBuilder text = new StringBuilder();

        public String getText() 
            return text.toString();
        

        public void append(String input) 
            text.append(input);
        

        public Snapshot createSnapshot() 
            return new Snapshot(text.toString());
        

        //储存快照
        public void restoreSnapshot(Snapshot snapshot) 
            this.text.replace(0, this.text.length(), snapshot.getText());
        
    

    static class Snapshot 
        private String text;

        public Snapshot(String text) 
            this.text = text;
        

        public String getText() 
            return this.text;
        
    

    static class SnapshotHolder 
        private Stack<Snapshot> snapshots = new Stack<>();

        public Snapshot popSnapshot() 
            return snapshots.pop();
        

        public void pushSnapshot(Snapshot snapshot) 
            snapshots.push(snapshot);
        
    


    public static void main(String[] args) 
        InputText inputText = new InputText();
        SnapshotHolder snapshotsHolder = new SnapshotHolder();
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) 
            String input = scanner.next();
            if (input.equals(":list")) 
                System.out.println(inputText.toString());
             else if (input.equals(":undo")) 
                Snapshot snapshot = snapshotsHolder.popSnapshot();
                inputText.restoreSnapshot(snapshot);
             else 
                snapshotsHolder.pushSnapshot(inputText.createSnapshot());
                inputText.append(input);
            
        
    

20.命令模式

概念:
命令模式将请求(命令)封装为一个对象,这样可以使用不同的请求参数化其他对象(将不同请求依赖注入到其他对象),
并且能够支持请求(命令)的排队执行、记录日志、撤销等(附加控制)功能。
示例:
手游后端服务器轮询获取客户端发来的请求,获取到请求之后,借助命令模式,
把请求包含的数据和处理逻辑封装为命令对象,并存储在内存队列中。然后,再从队列中取出一定数量的命令来执行。
执行完成之后,再重新开始新的一轮轮询

enum Event 
        GOT_STAR, HIT_OBSTACLE, ARCHIVE
    

    static class Request 
        Event mEvent;

        public Event getEvent() 
            return mEvent;
        
    

    public interface Command 
        void execute();
    

    static class HitObstacleCommand implements Command 
        public HitObstacleCommand(/*数据*/) 
        

        @Override
        public void execute() 
        
    

    static class ArchiveCommand implements Command 
        public ArchiveCommand(/*数据*/) 
        

        @Override
        public void execute() 
        
    

    static class GotStartCommand implements Command 
        public GotStartCommand(/*数据*/) 
        

        @Override
        public void execute() 
        
    

    private static final int MAX_HANDLED_REQ_COUNT_PER_LOOP = 100;
    private static Queue<Command> queue = new LinkedList<>();

    static void mainloop() 
        while (true) 
            List<Request> requests = new ArrayList<>();
            //省略从epoll或者select中获取数据,并封装成Request的逻辑,
            //注意设置超时时间,如果很长时间没有接收到请求,就继续下面的逻辑处理。
            for (Request request : requests) 
                Event event = request.getEvent();
                Command command = null;
                if (event.equals(Event.GOT_STAR)) 
                    command = new GotStartCommand(/*数据*/);
                 else if (event.equals(Event.HIT_OBSTACLE)) 
                    command = new HitObstacleCommand(/*数据*/);
                 else if (event.equals(Event.ARCHIVE)) 
                    command = new ArchiveCommand(/*数据*/);
                 // ...一堆else if...
                queue.add(command);
            
            int handledCount = 0;
            while (handledCount < MAX_HANDLED_REQ_COUNT_PER_LOOP) 
                if (queue.isEmpty()) 
                    break;
                
                Command command = queue.poll();
                command.execute();
            
        
    

21.解释器模式

概念:
解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器用来处理这个语法。
它的代码实现的核心思想,就是将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。
示例:
比如“ 8 3 2 4 - + * ”这样一个表达式,我们按照上面的语法规则来处理,取出数字“8 3”和“-”运算符,计算得到5,
于是表达式就变成了“ 5 2 4 + * ”。然后,我们再取出“ 5 2 ”和“ + ”运算符,计算得到7,
表达式就变成了“ 7 4 * ”。最后,我们取出“ 7 4”和“ * ”运算符,最终得到的结果就是28。
在这里就是把数字与表达式计算解藕成单独的子类

public interface Expression 
        long interpret();
    

    static class NumberExpression implements Expression 
        private long number;

        public NumberExpression(long number) 
            this.number = number;
        

        public NumberExpression(String number) 
            this.number = Long.parseLong(number);
        

        @Override
        public long interpret() 
            return this.number;
        
    

    static class AdditionExpression implements Expression 
        private Expression exp1;
        private Expression exp2;

        public AdditionExpression(Expression exp1, Expression exp2) 
            this.exp1 = exp1;
            this.exp2 = exp2;
        

        @Override
        public long interpret() 
            return exp1.interpret() + exp2.interpret();
        
    
    // SubstractionExpression/MultiplicationExpression/DivisionExpression与AdditionExpression代码结构类似,这里就省略了

    static class ExpressionInterpreter 
        private Deque<Expression> numbers = new LinkedList<>();

        public long interpret(String expression) 
            String[] elements = expression.split(" ");
            int length = elements.length;
            for (int i = 0; i < (length + 1) / 2; ++i) 
                numbers.addLast(new NumberExpression(elements[i]));
            
            for (int i = (length + 1) / 2; i < length; ++i) 
                String operator = elements[i];
                boolean isValid = "+".equals(operator) || "-".equals(operator)
                                  || "*".equals(operator) || "/".equals(operator);
                if (!isValid) 
                    throw new RuntimeException("Expression is invalid: " + expression);
                

                Expression exp1 = numbers.pollFirst();
                Expression exp2 = numbers.pollFirst();
                Expression combinedExp = null;
                if (operator.equals("+")) 
                    combinedExp = new AdditionExpression(exp1, exp2);
                 else if (operator.equals("-")) 
                    combinedExp = new AdditionExpression(exp1, exp2);
                 else if (operator.equals("*")) 
                    combinedExp = new AdditionExpression(exp1, exp2);
                 else if (operator.equals("/")) 
                    combinedExp = new AdditionExpression(exp1, exp2);
                
                long result = combinedExp.interpret();
                numbers.addFirst(new NumberExpression(result));
            

            if (numbers.size() != 1) 
                throw new RuntimeException("Expression is invalid: " + expression);
            

            return numbers.pop().interpret();
        
    

    public static void main(String[] args) 
        ExpressionInterpreter interpreter = new ExpressionInterpreter();
        System.out.println(interpreter.interpret("8 3 2 4 - + *") + "");
    

22.中介模式

概念:
中介模式定义了一个单独的(中介)对象,来封装一组对象之间的交互。将这组对象之间的交互委派给与中介对象交互,
来避免对象之间的直接交互。
中介模式的设计思想跟中间层很像,通过引入中介这个中间层,将一组对象之间的交互关系(或者说依赖关系)从多对多(网状关系)
转换为一对多(星状关系)。原来一个对象要跟n个对象交互,现在只需要跟一个中介对象交互,从而最小化对象之间的交互关系,
降低了代码的复杂度,提高了代码的可读性和可维护性。
示例:
假设我们有一个比较复杂的对话框,对话框中有很多控件,比如按钮、文本框、下拉框等。当我们对某个控件进行操作的时候,
其他控件会做出相应的反应,比如,我们在下拉框中选择“注册”,注册相关的控件就会显示在对话框中。
如果我们在下拉框中选择“登陆”,登陆相关的控件就会显示在对话框中。

public interface Mediator 
        void handleEvent(Object component, String event);
    

    static class LandingPageDialog implements Mediator 
        private Button loginButton;
        private Button regButton;
        private Selection selection;
        private EditText usernameInput;
        private EditText passwordInput;
        private EditText repeatedPswdInput;
        private Text hintText;

        @Override
        public void handleEvent(Object component, String event) 
            if (component.equals(loginButton)) 
                String username = usernameInput.getText().toString();
                String password = passwordInput.getText().toString();
                //校验数据...
                //做业务处理...
             else if (component.equals(regButton)) 
                //获取usernameInput、passwordInput、repeatedPswdInput数据...
                //校验数据...
                //做业务处理...
             else if (component.equals(selection)) 
                String selectedItem = selection.toString();
                if (selectedItem.equals("login")) 
                    //usernameInput.show();
                    //passwordInput.show();
                    //repeatedPswdInput.hide();
                    //hintText.hide();
                    //...省略其他代码
                 else if (selectedItem.equals("register")) 
                    //....
                
            
        

    

    static class UIControl 
        private static final String LOGIN_BTN_ID = "login_btn";
        private static final String REG_BTN_ID = "reg_btn";
        private static final String USERNAME_INPUT_ID = "username_input";
        private static final String PASSWORD_INPUT_ID = "pswd_input";
        private static final String REPEATED_PASSWORD_INPUT_ID = "repeated_pswd_input";
        private static final String HINT_TEXT_ID = "hint_text";
        private static final String SELECTION_ID = "selection";

        static Object findViewById(String id) 
            return null;
        

        public static void main(String[] args) 
            Button loginButton = (Button) findViewById(LOGIN_BTN_ID);
            Button regButton = (Button) findViewById(REG_BTN_ID);
            EditText usernameInput = (EditText) findViewById(USERNAME_INPUT_ID);
            EditText passwordInput = (EditText) findViewById(PASSWORD_INPUT_ID);
            EditText repeatedPswdInput = (EditText) findViewById(REPEATED_PASSWORD_INPUT_ID);
            Text hintText = (Text) findViewById(HINT_TEXT_ID);
            Selection selection = (Selection) findViewById(SELECTION_ID);

            Mediator dialog = new LandingPageDialog();
            //dialog.setLoginButton(loginButton);
            //dialog.setRegButton(regButton);
            //dialog.setUsernameInput(usernameInput);
            //dialog.setPasswordInput(passwordInput);
            //dialog.setRepeatedPswdInput(repeatedPswdInput);
            //dialog.setHintText(hintText);
            //dialog.setSelection(selection);

            loginButton.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                    dialog.handleEvent(loginButton, "click");
                
            );

            regButton.setOnClickListener(new View.OnClickListener() 
                @Override
                public void onClick(View v) 
                    dialog.handleEvent(regButton, "click");
                
            );

            //....
        
    

以上是关于23种设计模式归纳总结——行为型的主要内容,如果未能解决你的问题,请参考以下文章

23种设计模式归纳总结——行为型

23种设计模式归纳总结——创建型

23种设计模式归纳总结——创建型

23种设计模式归纳总结——创建型

23种设计模式归纳总结——创建型

23种设计模式