设计模式之行为模式(1)

行为型模式

 

术语

template:模板

角色

AbstractClass 抽象类实现了模板方法(template),定义了算法的骨架,具体子类需要去实现 其它的抽象方法ConcreteClass 2)实现抽象方法 , 以完成算法中特点子类的步骤

案例

​ 需求:统计某一代码运行时间

        使用前:

  • public class CodeTotalTime {
    
        public static void template(){
            long start = System.currentTimeMillis();
            //        检测Operation_1方法运行的时长======33
            Operation_1();
            //        检测Operation_2方法运行的时长======616
            //        Operation_2();
            long end = System.currentTimeMillis();
            System.out.println(end-start);
        }
    
        public static void Operation_1(){
    
            for (int i = 0; i<1000 ;i++){
                System.out.println("模拟耗时操作...");
            }
            System.out.print("检测Operation_1方法运行的时长======");
        }
    
        public static void Operation_2(){
    
            for (int i = 0; i<20000 ;i++){
                System.out.println("模拟耗时操作...");
            }
    
            System.out.print("检测Operation_2方法运行的时长======");
        }
    
    }
    
    
    public class Client {
        public static void main(String[] args) {
            CodeTotalTime.template();
        }
    }

    使用后:

  • abstract class CodeAbstractClass {
    	public void template() {
    		long start = System.currentTimeMillis();
    		method();
    		long end = System.currentTimeMillis();
    		System.out.println("当前方法执行时长:" + (end - start));
    	}
    
    	public abstract void method();
    }
    
    class ConcreteClassA extends CodeAbstractClass {
    	@Override
    	public void method() {
    		for (int i = 0; i < 1000; i++) {
    			System.out.println("模拟耗时操作...");
    		}
    		System.out.print("检测ConcreteClassA.method方法运行的时长======");
    	}
    }
    
    class ConcreteClassB extends CodeAbstractClass {
    	@Override
    	public void method() {
    		for (int i = 0; i < 20000; i++) {
    			System.out.println("模拟耗时操作...");
    		}
    		System.out.print("ConcreteClassB.method方法运行的时长======");
    	}
    }
    
    
    public class Client {    
    	public static void main(String[] args) {
    		//检测ConcreteClassA.method方法运行的时长======当前方法执行时长:
    		new ConcreteClassA().template();        
    		//ConcreteClassB.method方法运行的时长======当前方法执行时长:       
    		new ConcreteClassB().template();    
    	}
    }

    钩子函数应用场景:

  • 
    public abstract class CodeAbstractClass {
        public void template() {
            long start = System.currentTimeMillis();
            if (callback()) method();
            long end = System.currentTimeMillis();
            System.out.println("当前方法执行时长:" + (end - start));
        }
    
        public abstract void method();
    
        public boolean callback() {
            return true;
        }
    }
    

    从上面可以看出:template方法默认是用作统计method方法的执行时长,但是有的时候我们无需统计代码时长,template函数中有一些其它逻辑要执行,在这里我们可以考虑采用钩子函数;钩子函数被子类覆写,覆写成false,那么method方法就不会被调用,不再统计代码时长了;前端框架Vue的生命周期就有多处用到钩子函数;

  • 注意事项和细节

    • 钩子函数在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为“钩子”

    • 算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改

    • 一般模板方法都加上 final 关键字, 防止子类重写模板方法

  • 应用

    Spring IOC容器加载


命令模式(Command)

  • 术语

    • Command:命令

    • ConcreteCommand:具体的命令

    • Invoker:调用者

    • Receiver:接受者

标准UML类图

  • 角色

    • Command抽象命令 执行命令 撤销命令

    • ConcreteCommandLightOnCommand 开灯 LightOffCommand 关灯

      ​ NonCommand

      ​ 空命令

    • Invoker调用者 遥控器聚合所有命令 Command[] ons Command[] offs Command undo

    • Receiver接受者 电灯、空调、电视

  • 案例

    ​ 需求:万能遥控器的制作

    案例UML类图

注意事项和细节:

        将发起请求的对象与执行请求的对象解耦 容易实现对请求的撤销和重做 空命令也是一种设计模式,它为我们省去了判空的操作

​ 命令模式不足:​ 可能导致某些系统有过多的具体命令类,增加了系统的复杂度

​ 与外观模式相似:都是将多个功能聚合在一起​ 外观模式更多适用于维护;命令模式更多应用于设计;

  应用:

Spring框架中的JdbcTemplate类 容易设计一个命令队列。只要把命令对象放到列队,就可以多线程的执行命令 界面的一个按钮都是一条命令、模拟 CMD(DOS 命令)订单的撤销/恢复、触发- 反馈机制


备忘录模式(Memento)

术语:

Memento:备忘录

originator:发起者

Caretaker:守护者

UML类图

角色

originator 待保存状态的对象 ~ Hero

Memento

备忘录对象

Caretaker

存放备忘录对象的容器;可以是List、Map、或者单个Memento对象

可以保存多个 originator 对象的不同时间的状态

 

案例

需求:游戏人物大战后状态恢复

情况1:为一个对象保留一个状态

public class Hero {
    //    需要存档的属性:这里用一个state属性来表示,实际需要存档的属性可能会有很多
    private String state;

    public Hero(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }    //    将当前Hero对象实例进行备份

    public HeroMemento saveHero() {
        return new HeroMemento(this.state);
    }

    //    恢复上一个英雄状态
    public void getMemento(HeroMemento heroMemento) {
        this.state = heroMemento.getState();
    }
}


package com.zking.memento.demo1;

public class Caretaker {
    private HeroMemento heroMemento;

    public HeroMemento getHeroMemento() {
        return heroMemento;
    }

    public void setHeroMemento(HeroMemento heroMemento) {
        this.heroMemento = heroMemento;
    }
}

package com.zking.memento.demo1;

public class HeroMemento {
    private String state;

    public HeroMemento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

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

package com.zking.memento.demo1;

public class Client {
    public static void main(String[] args) {
        Hero hero = new Hero("状态1,满血状态");
        Caretaker caretaker = new Caretaker();
        caretaker.setHeroMemento(hero.saveHero());
        hero.setState("状态2:状态下滑");
        System.out.println("当前的状态===============" + hero.getState());
        hero.getMemento(caretaker.getHeroMemento());
        System.out.println("当前的状态===============" + hero.getState());
        caretaker.setHeroMemento(hero.saveHero());
        hero.setState("状态3:残血状态");
        hero.getMemento(caretaker.getHeroMemento());
        System.out.println("当前的状态===============" + hero.getState());
        caretaker.setHeroMemento(hero.saveHero());
        hero.setState("状态4:临死状态");
        caretaker.setHeroMemento(hero.saveHero());
    }
}

情况2:为一个对象保留多个状态

package com.zking.memento.demo2;

public class Hero {
    //    需要存档的属性:这里用一个state属性来表示,实际需要存档的属性可能会有很多
    private String state;

    public Hero(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }    //    将当前Hero对象实例进行备份

    public HeroMemento saveHero() {
        return new HeroMemento(this.state);
    }    //    恢复某一个英雄状态

    public void getMemento(Caretaker caretaker, int no) {
        this.state = caretaker.getMemento(no).getState();
    }
}

package com.zking.memento.demo2;

public class HeroMemento {
    private String state;

    public HeroMemento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

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

package com.zking.memento.demo2;

import java.util.ArrayList;
import java.util.List;

public class Caretaker {
    private List<HeroMemento> heroMementos = new ArrayList<>();

    public void addMemento(HeroMemento memento) {
        heroMementos.add(memento);
    }

    public HeroMemento getMemento(int no) {
        return heroMementos.get(no);
    }
}

package com.zking.memento.demo2;

public class Client {
    public static void main(String[] args) {
        Hero hero = new Hero("状态1,满血状态");
        Caretaker caretaker = new Caretaker();
        caretaker.addMemento(hero.saveHero());
        hero.setState("状态2:状态下滑");
        hero.setState("状态3:残血状态");
        caretaker.addMemento(hero.saveHero());
        hero.setState("状态4:临死状态");
        caretaker.addMemento(hero.saveHero());
        hero.setState("状态5:死亡状态");
        //        上面备份了1、3、4状态,我来恢复看看         
        System.out.println("当前的状态===============" + hero.getState());
        hero.getMemento(caretaker, 0);
        System.out.println("回复到状态1===============" + hero.getState());
        hero.getMemento(caretaker, 1);
        System.out.println("回复到状态3===============" + hero.getState());
        hero.getMemento(caretaker, 2);
        System.out.println("回复到状态4===============" + hero.getState());
    }
}

情况3:为多个对象保留一个状态

public class Caretaker {    private HashMap<Originator ,Memento> mementos = new HashMap();}

情况4:为多个对象保留多个对象

public class Caretaker {    private HashMap<Originator , List<Memento>> mementos  = new HashMap();}

注意事项和细节

  • 给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态

  • 实现了信息的封装,使得用户不需要关心状态的保存细节

 注意:如果类的成员变量过多,势必会占用比应用事务回滚 游戏的存档 Selenium动态解析资源树 较大的资源,而且每一次保存都会消耗一定的内存

应用

事务回滚

    游戏的存档

        Selenium动态解析资源树

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值