• 设计模式中的行为型


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

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

    观察者模式

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

    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敲了一遍,值得反复推敲。希望在以后阅读源码和自己设计的时候,能够熟练于心。

  • 相关阅读:
    css盒模型不同浏览器下解释不同 解决办法
    【META http-equiv="Content-Type" Content="text/html; Charset=*】意义详解
    淘宝2015年秋招在线笔试题
    mouseleave mouseout时候悬浮框不应该消失的时候消失了 css 解决办法
    ACM知识点分类
    2019牛客多校第九场 B.Quadratic equation
    扫描线算法
    可持久化数据结构(模板)
    luogu SP3267 DQUERY
    luogu2633 Count on a tree(树上LCA+主席树求区间第k小)
  • 原文地址:https://www.cnblogs.com/Keep-Going-Space/p/14767380.html
Copyright © 2020-2023  润新知