设计模式中的行为型

之前两篇文章中,创建型主要讲类的创建,结构型主要讲类的组合,行为型主要侧重类和类的交互。行为型占了设计模式中的一半,在源码中我们经常会看到这些设计模式。
行为型设计模式主要有以下几个

  • 观察者模式
  • 模板模式
  • 策略模式
  • 职责链模式
  • 状态机模式
  • 迭代器模式
  • 访问者模式
  • 命令模式
  • 解释器模式
  • 中介者模式

观察者模式

观察者模式主要用于对结果的通知处理,有点类似发布订阅,但是发布订阅可以多对多,观察者模式时一对多的形式。

import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;


import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class TestObserver {
    public static void main(String[] args) {
        WeatherConsole weatherConsole = new WeatherConsole();
        weatherConsole.registerNotifition(new TelNotifition());
        weatherConsole.registerNotifition(new EmailNotifition());
        weatherConsole.pubWeather("sun");
        weatherConsole.pubWeather("rain");
        weatherConsole.pubAsyncWeather("oh it's sun");
        weatherConsole.pubAsyncWeather("oh it's rainy day");
    }
}


interface Notifition {


    void notifyMsg(String msg);
}


class EmailNotifition implements Notifition {
    @Subscribe
    public void notifyMsg(String msg) {
        System.out.println("send Email" + msg);
    }
}


class TelNotifition implements Notifition {


    @Subscribe
    public void notifyMsg(String msg) {
        System.out.println("call telephone" + msg);
    }
}


class WeatherConsole {
    private EventBus eventBus = new EventBus();
    private EventBus asyncEventBus = new AsyncEventBus(new ThreadPoolExecutor(5, 5, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()));


    public void registerNotifition(Notifition notifition) {
        eventBus.register(notifition);
        asyncEventBus.register(notifition);
    }


    public void pubAsyncWeather(String weather) {
        asyncEventBus.post(weather);
    }


    public void pubWeather(String weather) {
        asyncEventBus.post(weather);
    }
}

模板模式

模板模式主要用于当两个类继承同一个接口,但是其实类中部分方法时相同的时候,这个时候用模板模式,主要为了复用和扩展。

public class TestTemplate {
    public static void main(String[] args) {
        ClazzEntity clazzEntity = new ClazzEntity();
        clazzEntity.setAuthor("germa");
        clazzEntity.setClazzName("Clazz Event");
        clazzEntity.setInfomation("clazz event is test class");


        DescriptionClazzEvent descriptionClazzEvent = new DescriptionClazzEvent();
        descriptionClazzEvent.setClazzEntity(clazzEntity);
        System.out.println(descriptionClazzEvent.getBasicInfo());
        System.out.println(descriptionClazzEvent.generateClazzId());


        BizClazzEvent bizClazzEvent = new BizClazzEvent();
        bizClazzEvent.setClazzEntity(clazzEntity);
        System.out.println(bizClazzEvent.getBasicInfo());
        System.out.println(bizClazzEvent.generateClazzId());




    }
}


abstract class ClazzEvent {
    protected ClazzEntity clazzEntity;


    public void setClazzEntity(ClazzEntity clazzEntity) {
        this.clazzEntity = clazzEntity;
    }


    public String getBasicInfo() {
        return clazzEntity.getInfomation();
    }


    public abstract String generateClazzId();


}


class DescriptionClazzEvent extends ClazzEvent {
    @Override
    public String generateClazzId() {
        return String.format("%s:%s:%s", clazzEntity.getInfomation(), clazzEntity.getAuthor(), clazzEntity.getClazzName());
    }
}


class BizClazzEvent extends ClazzEvent {
    @Override
    public String getBasicInfo() {
        return clazzEntity.getClazzName();
    }


    @Override
    public String generateClazzId() {
        return String.format("%s:%s", clazzEntity.getInfomation(), clazzEntity.getAuthor());
    }
}




class ClazzEntity {
    private String clazzName;
    private String author;
    private String infomation;


    public String getClazzName() {
        return clazzName;
    }


    public void setClazzName(String clazzName) {
        this.clazzName = clazzName;
    }


    public String getAuthor() {
        return author;
    }


    public void setAuthor(String author) {
        this.author = author;
    }


    public String getInfomation() {
        return infomation;
    }


    public void setInfomation(String infomation) {
        this.infomation = infomation;
    }
}

策略模式

策略模式主要用于更具不同的类型,选择不同的对象,一般我们经常用if else if 这种去创建,这样子做的不足则是将策略的定义,创建和使用在一起呢。策略模式一般和工厂模式整合。

public class TestStrategy {
    public static void main(String[] args) {
        System.out.println(CarFactory.getCarByType(CarType.ELE_CAR).name());
        System.out.println(CarFactory.getCarByType(CarType.MIX_CAR).name());
        System.out.println(CarFactory.getCarByType(CarType.OIL_CAR).name());
    }
}


interface Car {
    String name();


}


class EleCar implements Car {


    @Override
    public String name() {
        return "byd";
    }
}


class OilCar implements Car {


    @Override
    public String name() {
        return "bmw";
    }
}


class MixCar implements Car {


    @Override
    public String name() {
        return "wulin";
    }
}


enum CarType {
    ELE_CAR("ele car"),
    OIL_CAR("oil car"),
    MIX_CAR("mix car");
    private String type;


    private CarType(String type) {
        this.type = type;
    }
}


class CarFactory {
    private static Map<CarType, Car> carMap = new HashMap<CarType, Car>();
    static {
        carMap.put(CarType.ELE_CAR,new EleCar());
        carMap.put(CarType.OIL_CAR,new OilCar());
        carMap.put(CarType.MIX_CAR,new MixCar());
    }


    public static Car getCarByType(CarType carType){
        return carMap.get(carType);
    }
}

职责链模式

职责链模式我们在开源框架中经常会遇到,比如tomcat中filter,dubbo中的filter.那么它的作用是将请求和返回进行解耦。比如一个请求过来了,先传给A进行处理,再传给B进行处理,再传给C进行处理,一条链路下来。

public class TestChain {
    public static void main(String[] args) {
        FileChain fileChain = new FileChain();
        fileChain.addhandler(new LogHandler());
        fileChain.addhandler(new UnicodeHandler());
        fileChain.handle();
    }
}


abstract class Handler {
    protected Handler succedor = null;


    public void handle() {
        doHandle();
        if (succedor != null) {
            succedor.handle();
        }
    }


    public void setHandler(Handler handler) {
        this.succedor = handler;
    }


    abstract void doHandle();


}


class LogHandler extends Handler {


    @Override
    void doHandle() {
        System.out.println("add log");
    }
}


class UnicodeHandler extends Handler {
    @Override
    void doHandle() {
        System.out.println("translate unicode");
    }
}


class FileChain {
    //链表维护调用链
    private Handler head = null;
    private Handler tail = null;


    public void addhandler(Handler handler) {
        if (head == null) {
            head = handler;
            tail = handler;
        } else {
            tail.setHandler(handler);
            tail = handler;
        }
    }


    public void handle() {
        if (head != null) {
            head.handle();
        }
    }
}

状态模式

状态机一般用于状态转换,当处于某种状态下,其他操作应该有什么其他状态。比如打王者荣耀时,当碰到甄姬的溜溜球的时候,如果你的状态处于被溜溜球已经处于第二次的状态,则状态应该被冻住,同时发出冻住的声音,如果你的状态属于第一次的时候,则标记为两次被打中,发出打中声音。在这个过程只涉及状态更改,不涉及补偿状态等。状态机一般有三个部分组成:状态,事件,动作。事件也称转移条件。接下来这个例子,我找了文档上的一段说明。

public class TestState {
    public static void main(String[] args) {
        MarioMachine marioMachine = new MarioMachine();
        System.out.println(marioMachine.getScore()+"--"+marioMachine.getCurrentState().getName());
        marioMachine.obtainMushRoom();
        System.out.println(marioMachine.getScore()+"--"+marioMachine.getCurrentState().getName());
    }
}


enum State {
    SMALL("small"),
    SUPER("super");
    private String type;


    private State(String type) {
        this.type = type;
    }
}


class MarioMachine {
    private int score;
    private IMario currentState;


    public int getScore() {
        return score;
    }


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


    public MarioMachine() {
        this.score = 0;
        this.currentState = SmallMario.instance;
    }


    public void setCurrentState(IMario mario){
        this.currentState = mario;
    }


    public IMario getCurrentState() {
        return currentState;
    }


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


interface IMario {
    State getName();


    void obtainMushRoom(MarioMachine stateMachine);




    void meetMonster(MarioMachine stateMachine);
}


class SmallMario implements IMario {
    public static final SmallMario instance = new SmallMario();


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


    @Override
    public void obtainMushRoom(MarioMachine stateMachine) {
        stateMachine.setCurrentState(SupperMario.instance);
        stateMachine.setScore(stateMachine.getScore()+100);
    }








    @Override
    public void meetMonster(MarioMachine stateMachine) {
        stateMachine.setCurrentState(null);
        stateMachine.setScore(0);
    }
}


class SupperMario implements IMario{
    public static final SupperMario instance = new SupperMario();
    @Override
    public State getName() {
        return State.SUPER;
    }

    @Override
    public void obtainMushRoom(MarioMachine stateMachine) {
        stateMachine.setCurrentState(SupperMario.instance);
        stateMachine.setScore(stateMachine.getScore()+1000);
    }

    @Override
    public void meetMonster(MarioMachine stateMachine) {
        stateMachine.setCurrentState(SmallMario.instance);
        stateMachine.setScore(stateMachine.getScore()+1000);
    }
}

迭代器模式

迭代器模式我们其实在集合遍历的时候一直在使用。那么它和for 有什么区别呢,在数组,链表的迭代中差别不是很明显,但是像在图等复杂模型中,拥有更快捷的便利。

public class TestIterator {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("a");
        list.add("n");
        list.add("b");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String value = iterator.next();
            iterator.remove();
            System.out.println(value);
        }
        System.out.println(list.size());
    }
}

访问者模式

访问者模式我们通过在asm中用的最多。作用于将业务数据和业务操作分开。

public class TestExtractor {
    public static void main(String[] args){
        Extractor extractor = new Extractor();
        extractor.extract(new PDFFile());
    }
}




class Extractor{
    public void extract(ResourceFile resourceFile){
        System.out.println("extract file"+resourceFile.name());
        System.out.println("the text "+resourceFile.context());
    }
}


interface ResourceFile{
     String name();
     String context();
}


class PDFFile implements ResourceFile{


    @Override
    public String name() {
        return "PDF";
    }


    @Override
    public String context() {
        return "this is text";
    }
}

备忘录模式

备忘录模式通过一个单独的类或者其他的形式,将对象进行备份和恢复。

public class TestMemoto {
    public static void main(String[] args) {
        InputText text = new InputText();
        InputHolder inputHolder = new InputHolder();
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            String input = scanner.next();
            if (input.equals(":list")) {
                System.out.println(text.getText());
            } else if (input.equals(":undo")) {
                InputText snapshot = inputHolder.popSnapshot();
                text.setText(snapshot.getText());
            } else {
                inputHolder.stashSnapshot(text);
                text.append(input);
                System.out.println("----");
            }
        }
    }
}


class InputText {
    StringBuilder consoleText = new StringBuilder();


    public void setText(String text) {
        consoleText.replace(0, consoleText.length(), text);
    }


    public String getText() {
        return consoleText.toString();
    }


    public void append(String textStr) {
        consoleText.append(textStr);
    }


}


class InputHolder {
    private Stack<InputText> stack = new Stack<InputText>();


    public InputText popSnapshot() {
        return stack.pop();
    }


    public void stashSnapshot(InputText inputText) {
        InputText deepCopyInputText = new InputText();
        deepCopyInputText.append(inputText.getText());
        stack.push(deepCopyInputText);
    }
}

命令模式

命令模式和策略模式非常像。但是在使用上会有不同。策略模式时根据不同的策略选择不同的实现,但是目的都是一致的。命令模式是将请求封装成命令,进行执行。
解释器模式
解释器为了某种语言定义了它的语法,并通过解释器来处理这种语法。
中介者模式
中介者模式是当对象进行复杂交互时,通过中介类进行管理

以上就是设计模式中的行为型,基本上23种设计模式都讲完了,有些不理解的也按照demo敲了一遍,值得反复推敲。希望在以后阅读源码和自己设计的时候,能够熟练于心。

原文地址:https://www.cnblogs.com/Keep-Going-Space/p/14767380.html