设计模式--行为型模式

目录

模板模式(Template)

命令模式(Command)

备忘录模式(Memento)

状态模式(State)

职责链模式(Chain of Responsibility)

观察者模式(Observer)

策略模式(Strategy)


模板模式(Template)

术语

template:模板

模板模式UML类图  

角色

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

案例

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

 使用前

package com.javaty.design.template.before;

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 抽象命令                                                                                                                                                      执行命令                                                                                                                                      撤销命令

  • ConcreteCommand 具体命令                                                                                                                       LightOnCommand 开灯                                                                                                               LightOffCommand 关灯                                                                                                              ​ NonCommand ​ 空命令

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

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

  • 案例

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

    案例UML类图

出现前  

package com.javaty.design.command.before;

/**
 * 被操作的对象
 */
public class Light {
    public void on(){
        System.out.println("电灯打开...");
    }

    public void off(){
        System.out.println("电灯关闭...");
    }
}

class AirConditioner {
    public void on(){
        System.out.println("空调打开...");
    }

    public void off(){
        System.out.println("空调关闭...");
    }
}

class Television {
    public void on(){
        System.out.println("电视打开...");
    }

    public void off(){
        System.out.println("电视关闭...");
    }
}


public class Invoker {
    private Light light = new Light();
    private AirConditioner airConditioner = new AirConditioner();
    private Television television = new Television();

    public void lightOn(){
        light.on();
    }

    public void lightOff(){
        light.off();
    }

    public void airOn(){
        airConditioner.on();
    }

    public void airOff(){
        airConditioner.off();
    }

    public void tvOn(){
        television.on();
    }

    public void tvOff(){
        television.off();
    }
}

public class Client {
    public static void main(String[] args) {
        Invoker invoker = new Invoker();
        invoker.lightOn();
        invoker.lightOff();
        System.out.println("=============");
        invoker.airOn();
        invoker.airOff();
        System.out.println("=============");
        invoker.tvOn();
        invoker.tvOff();
    }
}

出现后

package com.javaty.design.command.after;

/**
 * 被操作的对象
 */
public class Light {
    public void on(){
        System.out.println("电灯打开...");
    }

    public void off(){
        System.out.println("电灯关闭...");
    }
}

class AirConditioner {
    public void on(){
        System.out.println("空调打开...");
    }

    public void off(){
        System.out.println("空调关闭...");
    }
}

class Television {
    public void on(){
        System.out.println("电视打开...");
    }

    public void off(){
        System.out.println("电视关闭...");
    }
}


package com.javaty.design.command.after;


interface Command {
    void execute();

    void undo();
}

//空命令
class NonCommand implements Command {

    @Override
    public void execute() {

    }

    @Override
    public void undo() {

    }
}

class LightOnCommand implements Command {
    private Light light = new Light();

    @Override
    public void execute() {
        light.on();
    }

    @Override
    public void undo() {
        light.off();
    }
}

class LightOffCommand implements Command {
    private Light light = new Light();

    @Override
    public void execute() {
        light.off();
    }

    @Override
    public void undo() {
        light.on();
    }
}

class TvOnCommand implements Command {
    private Television tv = new Television();

    @Override
    public void execute() {
        tv.on();
    }

    @Override
    public void undo() {
        tv.off();
    }
}

class TvOffCommand implements Command {
    private Television tv = new Television();

    @Override
    public void execute() {
        tv.off();
    }

    @Override
    public void undo() {
        tv.on();
    }
}


public class Invoker {
    Command[] ons;
    Command[] offs;
//    记录上一个命令
    Command command;

    public Invoker(int n) {
        ons = new Command[n];
        offs = new Command[n];
        command = new NonCommand();
        for (int i = 0; i < n; i++) {
            setCommand(i,new NonCommand(),new NonCommand());
        }
    }

    public void setCommand(int no, Command on, Command off){
        ons[no]=on;
        offs[no]=off;
    }

    public Command getOnCommand(int no){
        return ons[no];
    }

    public Command getOffCommand(int no){
        return offs[no];
    }

//    执行命令
    public void invoke(Command command){
//        执行当前命令
        command.execute();
//        保存当前执行命令
        this.command = command;
    }

//    撤销命令(上个操作的反操作)
    public void undo(){
//        这里就能体现定义一个空命令的好处了,如果第一次按撤销命令,那么应该什么都不做;
//        如果没有定义空命令的话,此时就需要判断空处理了
        command.undo();
    }
}


public class Client {
    public static void main(String[] args) {
        Invoker invoker = new Invoker(2);
        invoker.setCommand(0, new LightOnCommand(), new LightOffCommand());
        invoker.setCommand(1, new TvOnCommand(), new TvOffCommand());

        System.out.println("电灯打开关闭操作===========");
        invoker.invoke(invoker.getOnCommand(0));
        invoker.invoke(invoker.getOffCommand(0));
//        invoker.undo();
        System.out.println("电视打开关闭操作===========");
        invoker.invoke(invoker.getOnCommand(1));
        invoker.undo();
    }
}

 

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

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

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

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

备忘录模式(Memento)

  • 术语

    Memento:备忘录                                                                                                                  originator:发起者                                                                                                    Caretaker:守护者

UML类图

  • 角色

    originator                                                                                                                                              待保存状态的对象 ~ Hero                                                                                                Memento                                                                                                                                               备忘录对象                                                                                                              Caretaker                                                                                                                                             存放备忘录对象的容器;可以是List、Map、或者单个Memento对象                                         可以保存多个 originator 对象的不同时间的状态

  • 案例

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

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

  package com.javaty.design.memento.one;
  
 
  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();
      }
  
  }
  
  
  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;
      }
  }
  
  
  public class Caretaker {
      private HeroMemento heroMemento;
  
      public HeroMemento getHeroMemento() {
          return heroMemento;
      }
  
      public void setHeroMemento(HeroMemento heroMemento) {
          this.heroMemento = heroMemento;
      }
  }
  
  
  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:为一个对象保留多个状态

  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();
      }
  
  }
  
  
  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;
      }
  }
  
  
  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);
      }
  
  }
  
  
  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动态解析资源树

 

状态模式(State)

  • 术语

    State:状态

  • 角色

    Context:环境角色:用于维护 State 实例,这个实例定义当前状态                                        State:抽象状态角色:聚合到Context环境角色中                                                        ConcreteState :具体的状态角色                                                                                                                   ConcreteStateA                                                                                                                           ConcreteStateB                                                                                                                           ConcreteStateC

UML类图

 

案例

案例:抽奖活动项目设计

 

出现前  

package com.javaty.design.state.before;

import java.util.Random;

public class State {
    //    当前的状态
    private int state;
    //    供抽奖的积分
    private int score;
    //    奖品的数量
    private int count;

    public State(int score, int count) {
        this.score = score;
        this.count = count;
    }

    public int getCount() {
        return count;
    }

    public int getState() {
        return state;
    }

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

    public int getScore() {
        return score;
    }

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

    //    扣除积分
    public void minus() {
//        只有一阶段可以扣积分
        this.state = 1;
        if (this.state == 1) {
            if (this.score >= 50) {
                if (this.count == 0) {
                    System.out.println("奖品领完....");
                    return;
                }
                this.score = this.score - 50;
                System.out.println("========扣除50积分,当前积分还剩" + this.score + "========");
                this.state = 2;
                if (luckHit()) {
                    this.state = 3;
                    getPrize();
                }
            } else {
                System.out.println("========积分不够,当前积分为" + this.score + "========");
            }
        }

    }

    //    十分之一抽中奖品的概率
    public boolean luckHit() {
//        只有二阶段可以抽奖
        return this.state == 2 ? (new Random().nextInt(10) == 6) : false;
    }

    public void getPrize() {
        if (this.state == 3) {
            if (this.count > 0) {
                System.out.println("领取奖品....");
                this.count = this.count - 1;
            } else {
                System.out.println("奖品领完....");
            }
        }
    }

}


public class Client {
    public static void main(String[] args) {
        State state = new State(500,1);
//        state.minus();
        for (int i = 0; i < 300; i++) {
            state.minus();
        }
    }
}

 从上面的编码中,我们可以看出,完成该需求有很多的条件判断,非常不利于后续的维护;上面状态只有4个,代码已经比较复杂了;状态越多,代码嵌套就越复杂,维护成本就越高;

出现后

package com.javaty.design.state.after;

import java.util.Random;


public abstract class State {

//    扣积分
    abstract void minus();
//    抽奖
    abstract boolean luckHit();
//    获取奖品
    abstract void getPrize();

}

class ConcreteStateA extends State{
    Context context;

    public ConcreteStateA(Context context) {
        this.context = context;
    }

    @Override
    void minus() {
        if(context.getScore()>=50){
            context.setScore(context.getScore()-50);
            System.out.println("========扣除50积分,当前积分还剩"+context.getScore()+"========");
            context.setState(context.getStateB());
        }else{
            System.out.println("========积分不够,当前积分为"+context.getScore()+"========");
        }
    }

    @Override
    boolean luckHit() {
        System.out.println("还在扣费环节,不能抽奖...");
        return false;
    }

    @Override
    void getPrize() {
        System.out.println("还在扣费环节,不能领取奖品...");
    }
}

class ConcreteStateB extends State{
    Context context;

    public ConcreteStateB(Context context) {
        this.context = context;
    }

    @Override
    void minus() {
        System.out.println("已经在抽奖环节...");
    }

    @Override
    boolean luckHit() {
        boolean flag = new Random().nextInt(10) == 6;
        if(flag){
            context.setState(context.getStateC());
        }else{
            context.setState(context.getStateA());
        }
        return flag;
    }

    @Override
    void getPrize() {
        System.out.println("还在抽奖环节,不能领取奖品...");
    }
}

class ConcreteStateC extends State{
    Context context;

    public ConcreteStateC(Context context) {
        this.context = context;
    }

    @Override
    void minus() {
        System.out.println("已经在领取奖品环节...");
    }

    @Override
    boolean luckHit() {
        System.out.println("已经在领取奖品环节...");
        return false;
    }

    @Override
    void getPrize() {
        if(context.getCount()>0){
            System.out.println("领取奖品成功...");
            context.setState(context.getStateA());
        }else {
            System.out.println("活动结束,领取奖品失败...");
            context.setState(context.getStateD());
//            不继续抽奖
//            System.exit(0);
        }
    }
}

class ConcreteStateD extends State{
    Context context;

    public ConcreteStateD(Context context) {
        this.context = context;
    }

    @Override
    void minus() {
        System.out.println("已经在活动结束,奖品送完环节...");
    }

    @Override
    boolean luckHit() {
        System.out.println("已经在活动结束,奖品送完环节...");
        return false;
    }

    @Override
    void getPrize() {
        System.out.println("已经在活动结束,奖品送完环节...");
    }
}


public class Context {
    //    当前的状态
    private State state;
    //    奖品数量
    public int count;
    //    用户积分
    private int score;

    //    表示同一个对象的四种状态
    private ConcreteStateA stateA = new ConcreteStateA(this);
    private ConcreteStateB stateB = new ConcreteStateB(this);
    private ConcreteStateC stateC = new ConcreteStateC(this);
    private ConcreteStateD stateD = new ConcreteStateD(this);


    public Context(int score, int count) {
        this.score = score;
        this.count = count;
        this.state = stateA;
    }

    //    扣积分
    public void minus() {
        state.minus();
    }

    //    抽奖
    public void luckHit() {
        if (state.luckHit()) {
            state.getPrize();
        }
    }

    public State getState() {
        return state;
    }

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

    public int getCount() {
        return count--;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public ConcreteStateA getStateA() {
        return stateA;
    }

    public void setStateA(ConcreteStateA stateA) {
        this.stateA = stateA;
    }

    public ConcreteStateB getStateB() {
        return stateB;
    }

    public void setStateB(ConcreteStateB stateB) {
        this.stateB = stateB;
    }

    public ConcreteStateC getStateC() {
        return stateC;
    }

    public void setStateC(ConcreteStateC stateC) {
        this.stateC = stateC;
    }

    public ConcreteStateD getStateD() {
        return stateD;
    }

    public void setStateD(ConcreteStateD stateD) {
        this.stateD = stateD;
    }

    public int getScore() {
        return score;
    }

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


public class Client {
    public static void main(String[] args) {
//        这次游戏积分500个,用完为止,总奖品数2
        Context context = new Context(500,1);
//        context.lunkHit();//还在扣费环节,不能抽奖...

        for (int i = 0; i < 300; i++) {
            context.minus();
            context.luckHit();
        }
        System.out.println("------------------");

    }
}
  • 注意事项和细节

    • 代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中(将每一个状态当成一个对象处理)

    • 方便维护。将容易产生问题的 if-else 语句删除了

    • 符合“开闭原则”。容易增删状态

​ 缺点:会产生很多类。每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度

​ 应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候, 可以考虑使用状态模式

  • 应用

    借贷平台状态管理

职责链模式(Chain of Responsibility)

 

  • 术语

    Chain of Responsibility:责任链

  • 角色

    Handler 抽象的处理者, 定义了一个处理请求的接口ConcreteHandlerA , B 具体的处理者, 处理它自己负责的请求, 可以访问它的后继者(即下一个处理者)Request 含义很多属性,表示一个请求

  • 案例

    需求:OA系统请假审批案例

    ​ 学生请假1天:教员审批

    ​ 学生请假2天:教学主管审批

    ​ 学生请假3天:教学经理审批

    ​ 学生请假5天:副校长审批

    ​ 学生请假超过5天:校长审批

    • 使用前

      
      package com.javaty.design.chain.before;
      
      
      public class Request {
          private String content;
          private int day;
      
          public Request(String content, int day) {
              this.content = content;
              this.day = day;
          }
      
          public String getContent() {
              return content;
          }
      
          public void setContent(String content) {
              this.content = content;
          }
      
          public int getDay() {
              return day;
          }
      
          public void setDay(int day) {
              this.day = day;
          }
      }
      
      
      package com.javaty.design.chain.before;
      
      
      public class Handler {
      
          public void handle(Request request){
              int day = request.getDay();
              if(day <= 1){
                  System.out.println("教员处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
              }else if(day <= 2){
                  System.out.println("教学主管处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
              }else if(day <= 3){
                  System.out.println("教学经理处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
              }else if(day <= 5){
                  System.out.println("副校长处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
              }else {
                  System.out.println("校长处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
              }
          }
      }
      
      
      public class Client {
          public static void main(String[] args) {
              Handler handler = new Handler();
              Request request1 = new Request("小感冒",1);
              handler.handle(request1);
      
              Request request2 = new Request("做检查",2);
              handler.handle(request2);
      
              Request request3 = new Request("打点滴",3);
              handler.handle(request3);
      
      
              Request request4 = new Request("住院",4);
              handler.handle(request4);
      
              Request request5 = new Request("在家调养",30);
              handler.handle(request5);
          }
      }

    违背了迪米特法则,调用方清楚的知道整个处理链的存在;

    • 使用后

      public class Request {
          private String content;
          private int day;
      
          public Request(String content, int day) {
              this.content = content;
              this.day = day;
          }
      
          public String getContent() {
              return content;
          }
      
          public void setContent(String content) {
              this.content = content;
          }
      
          public int getDay() {
              return day;
          }
      
          public void setDay(int day) {
              this.day = day;
          }
      }
      
      public abstract class Handler {
          Handler next;
          String name;
      
          public Handler(String name) {
              this.name = name;
          }
      
          public Handler getNext() {
              return next;
          }
      
          public void setNext(Handler next) {
              this.next = next;
          }
      
          public abstract void handle(Request request);
      }
      
      class HandlerA extends Handler {
          public HandlerA(String name) {
              super(name);
          }
      
          public void handle(Request request) {
              int day = request.getDay();
              if (day <= 1) {
                  System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
              } else {
                  next.handle(request);
              }
          }
      }
      
      class HandlerB extends Handler {
          public HandlerB(String name) {
              super(name);
          }
      
          public void handle(Request request) {
              int day = request.getDay();
              if (day <= 2) {
                  System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
              } else {
                  next.handle(request);
              }
          }
      }
      
      class HandlerC extends Handler {
          public HandlerC(String name) {
              super(name);
          }
      
          public void handle(Request request) {
              int day = request.getDay();
              if (day <= 3) {
                  System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
              } else {
                  next.handle(request);
              }
          }
      }
      
      class HandlerD extends Handler {
          public HandlerD(String name) {
              super(name);
          }
      
          public void handle(Request request) {
              int day = request.getDay();
              if (day <= 5) {
                  System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
              } else {
                  next.handle(request);
              }
          }
      }
      
      class HandlerE extends Handler {
          public HandlerE(String name) {
              super(name);
          }
      
          public void handle(Request request) {
              int day = request.getDay();
              System.out.println(this.name + "处理了:因 " + request.getContent() + " 请假" + day + "天的请求");
          }
      }
      
      
      public class Client {
          public static void main(String[] args) {
              HandlerA handlerA = new HandlerA("教员");
              HandlerB handlerB = new HandlerB("教学主管");
              HandlerC handlerC = new HandlerC("教学经理");
              HandlerD handlerD = new HandlerD("副校长");
              HandlerE handlerE = new HandlerE("校长");
              handlerA.setNext(handlerB);
              handlerB.setNext(handlerC);
              handlerC.setNext(handlerD);
              handlerD.setNext(handlerE);
      
              Request request1 = new Request("小感冒",1);
              handlerA.handle(request1);
      
              Request request2 = new Request("做检查",2);
              handlerA.handle(request2);
      
              Request request3 = new Request("打点滴",3);
              handlerA.handle(request3);
      
      
              Request request4 = new Request("住院",4);
              handlerA.handle(request4);
      
              Request request5 = new Request("在家调养",30);
              handlerA.handle(request5);
          }
      }
      
      

  • 注意事项和细节

    将请求和处理分开,实现解耦,提高系统的灵活性                                                                    简化了对象(比现最小原则),使对象不需要知道链的结构

​       注意:性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在 Handler 中设置一个最大节点数量,在 setNext()方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能

  • 应用

    springmvc框架~HandlerExcutionChain类                                                                                工作流框架绘图生成xml反射实例化,整个流程归档过程                                                          js中的原型链

观察者模式(Observer)

  • 术语

    Observer:观察者

    Subject:主题

  • 角色

  • Observer                                                                                                                                     观察者                                                                                                                                                      百度                                                                                                                                            新浪                                                                                                                                            谷歌                                                                                                                    Subject                                                                                                                                              气象局                                                                                                                                                  WeatherData

UML类图

 

  • 案例

    需求:气象站数据更新推送问题

    • 出现前

    
    package com.javaty.design.observer.before;
    
    public class WeatherData {
        double temperature;
        double humidity;
    
        public WeatherData(double temperature, double humidity) {
            this.temperature = temperature;
            this.humidity = humidity;
        }
    
        public void getWeatherInfo() {
            System.out.println("当前温度:" + temperature + ",当前湿度:" + humidity);
        }
    
        public void change(double temperature, double humidity) {
            this.temperature = temperature;
            this.humidity = humidity;
        }
    }
    
    
    
    public class Baidu {
        private WeatherData weatherData;
    
        public Baidu(WeatherData weatherData) {
            this.weatherData = weatherData;
        }
    
        public void getWeatherInfo() {
            System.out.print("百度网站温馨提示===>");
            weatherData.getWeatherInfo();
        }
    }
    
    class Sina {
        private WeatherData weatherData;
    
        public Sina(WeatherData weatherData) {
            this.weatherData = weatherData;
        }
    
        public void getWeatherInfo() {
            System.out.print("新浪网站温馨提示===>");
            weatherData.getWeatherInfo();
        }
    }
    
    
    public class Client {
        public static void main(String[] args) {
            WeatherData weatherData = new WeatherData(30,20);
            Baidu baidu = new Baidu(weatherData);
            Sina sina = new Sina(weatherData);
            baidu.getWeatherInfo();
            sina.getWeatherInfo();
            weatherData.change(10,10);
            baidu.getWeatherInfo();
            sina.getWeatherInfo();
        }
    }

    由第三方(百度、新浪)主动获取最新天气信息,这种方案需要每个第三方主动定时获取最新天气数据,涉及多个第三方;

    • 出现后

package com.javaty.design.observer.after;

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


public interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

class WeatherData implements Subject{
    double temperature;
    double humidity;
    List<Observer> Observers = new ArrayList<>();

    public WeatherData(double temperature, double humidity) {
        this.temperature = temperature;
        this.humidity = humidity;
    }

    public void update(double temperature, double humidity) {
        this.temperature = temperature;
        this.humidity = humidity;
//        气象局数据一改变,马上通知接入的第三方/观察者
        notifyObservers();
    }

    @Override
    public void addObserver(Observer observer) {
        Observers.add(observer);
        observer.update(this.temperature,this.humidity);
    }

    @Override
    public void removeObserver(Observer observer) {
        Observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : Observers) {
            observer.update(this.temperature,this.humidity);
        }
    }
}


public interface Observer {
    void display();
    void update(double temperature, double humidity);
}

class Baidu implements Observer{
    double temperature;
    double humidity;

    @Override
    public void display() {
        System.out.println("百度温馨提示:当前温度:" + temperature + ",当前湿度:" + humidity);
    }

    @Override
    public void update(double temperature, double humidity) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.display();
    }
}

class Sina implements Observer{
    double temperature;
    double humidity;

    @Override
    public void display() {
        System.out.println("新浪温馨提示:当前温度:" + temperature + ",当前湿度:" + humidity);
    }

    @Override
    public void update(double temperature, double humidity) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.display();
    }
}

public class Client {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData(30, 20);
        Baidu baidu = new Baidu();
        Sina sina = new Sina();
        weatherData.addObserver(baidu);
        weatherData.addObserver(sina);
        weatherData.update(10, 10);
        weatherData.removeObserver(baidu);
        weatherData.update(12, 12);
    }
}

由气象局主动通知第三方,天气数据发生了改变;并且,第三方(观察者)的接入可以控制(增加删除通知);

  • 注意事项和细节

    集合的方式来管理用户(Observer),包括注册,移除和通知

  • 应用

    JDK源码中Observable类

策略模式(Strategy)

  • 术语

    Strategy:策略

  • 角色

    Context                                                                                                                                               环境                                                                                                                                Strategy                                                                                                                                            策略接口                                                                                                                                              ConcreteStrategyA                                                                                                                      ConcreteStrategyB                                                                                                      Strategy2                                                                                                                                          策略接口                                                                                                                                             ConcreteStrategyC                                                                                                                     ConcreteStrategyD

  • 案例

    需求:学院共有专业需求

    • 出现前

      package com.javaty.design.strategy.before;
      
      public class Major {
          private String name;
      
          public Major(String name) {
              this.name = name;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          @Override
          public boolean equals(Object obj) {
              Major major = (Major) obj;
              return this.name.equals(major.name);
          }
      }
      
      
      public class College {
          String name;
      
          public College(String name) {
              this.name = name;
          }
      }
      
      class CollegeA extends College{
          List<Major> list = new ArrayList<>();
          CollegeA(String name){
              super(name);
              this.list.add(new Major("JAVA"));
              this.list.add(new Major("PHP"));
              this.list.add(new Major("JavaScript"));
              this.list.add(new Major("C语言"));
              this.list.add(new Major("android"));
          }
      }
      
      class CollegeB extends College{
          List<Major> list = new ArrayList<>();
          CollegeB(String name){
              super(name);
              this.list.add(new Major("iOS"));
              this.list.add(new Major("PHP"));
              this.list.add(new Major("JavaScript"));
              this.list.add(new Major("C语言"));
              this.list.add(new Major("嵌入式"));
          }
      }
      
      
      public class StrategyA {
          public List<Major> intersect(List<Major> a,List<Major> b){
              List<Major> list = new ArrayList();
              for (Major major : a) {
                  if(b.contains(major)){
                      list.add(major);
                  }
              }
              return list;
          }
      }
      
      class StrategyB {
          public List<Major> intersect(List<Major> a,List<Major> b){
      //        a.retainAll(b);
              b.retainAll(a);
              return b;
          }
      }
      
      public class Client {
          public static void main(String[] args) {
              StrategyA strategyA = new StrategyA();
              CollegeA a = new CollegeA("华东交通大学");
              CollegeB b = new CollegeB("东华理工大学");
              List<Major> intersect = strategyA.intersect(a.list, b.list);
              System.out.println(a.name + "与" + b.name + "都有的专业");
              for (Major major : intersect) {
                  System.out.println(major.getName());
              }
      
              StrategyB strategyB = new StrategyB();
              List<Major> intersect2 = strategyB.intersect(a.list, b.list);
              System.out.println(a.name + "与" + b.name + "都有的专业");
              for (Major major : intersect2) {
                  System.out.println(major.getName());
              }
          }
      }
    • 出现后

      package com.javaty.design.strategy.after;
      
      public class Major {
          private String name;
      
          public Major(String name) {
              this.name = name;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          @Override
          public boolean equals(Object obj) {
              Major major = (Major) obj;
              return this.name.equals(major.name);
          }
      }
      
      
      public class College {
          String name;
      
          public College(String name) {
              this.name = name;
          }
      }
      
      class CollegeA extends College {
          List<Major> list = new ArrayList<>();
          CollegeA(String name){
              super(name);
              this.list.add(new Major("JAVA"));
              this.list.add(new Major("PHP"));
              this.list.add(new Major("JavaScript"));
              this.list.add(new Major("C语言"));
              this.list.add(new Major("android"));
          }
      }
      
      class CollegeB extends College {
          List<Major> list = new ArrayList<>();
          CollegeB(String name){
              super(name);
              this.list.add(new Major("iOS"));
              this.list.add(new Major("PHP"));
              this.list.add(new Major("JavaScript"));
              this.list.add(new Major("C语言"));
              this.list.add(new Major("嵌入式"));
          }
      }
      
      public interface Strategy {
          List<Major> intersect(List<Major> a, List<Major> b);
      }
      
      public class StrategyA implements Strategy{
          public List<Major> intersect(List<Major> a,List<Major> b){
              List<Major> list = new ArrayList();
              for (Major major : a) {
                  if(b.contains(major)){
                      list.add(major);
                  }
              }
              return list;
          }
      }
      
      public class Context {
          public List<Major> intersect(List<Major> a, List<Major> b,Strategy strategy){
              return strategy.intersect(a,b);
          }
      }
      
      public class Client {
          public static void main(String[] args) {
              CollegeA a = new CollegeA("华东交通大学");
              CollegeB b = new CollegeB("东华理工大学");
              Context context = new Context();
      
              List<Major> intersect = context.intersect(a.list, b.list, new StrategyA());
              System.out.println(a.name + "与" + b.name + "都有的专业");
              for (Major major : intersect) {
                  System.out.println(major.getName());
              }
      
      //        可以随意定制策略
              List<Major> intersect2 = context.intersect(a.list, b.list, new Strategy() {
                  @Override
                  public List<Major> intersect(List<Major> a, List<Major> b) {
                      a.retainAll(b);
                      return a;
                  }
              });
              System.out.println(a.name + "与" + b.name + "都有的专业========");
              for (Major major : intersect2) {
                  System.out.println(major.getName());
              }
          }
      }
      

  • 注意事项和细节

    • 分析项目中变化部分不变部分(对它们进行设计)

    • 体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为) 即可

    • 策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改变它,使它易于切换、易于理解、易于扩展

​ 注意:在很多场景中,策略接口会作为内部接口体现

  • 应用

    • Arrays工具类的排序方法Comparator策略接口的使用

    • Basedao的Resultset的处理

    • 交集并集

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值