栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

行为型模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

行为型模式

模板方法模式(Template)
  • 术语

    template:模板

模板模式UML类图

  • 角色

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

  • 案例

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

  • 使用前

package com.javaxl.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.zking.command.demo1;

}

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.zking.command.demo1;
​    

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();
    }
}

package com.zking.command.demo1;

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();
    }
}
  • 出现后
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("电视关闭...");
	}
}
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.zking.memento.demo1;


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 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 mementos = new HashMap();}

略...

  • 情况4:为多个对象保留多个对象
public class Caretaker {    private HashMap> mementos  = new HashMap();}

略...

  • 注意事项和细节

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

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

注意:如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存

  • 应用   

       事务回滚

          游戏的存档

             Selenium动态解析资源树

状态模式(State)
  • 术语

    State:状态

  • 角色

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

UML类图

  • 案例

       案例:抽奖活动项目设计

  • 出现前

package com.javaxl.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.javaxl.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.javaxl.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.javaxl.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.javaxl.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.javaxl.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 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.javaxl.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 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 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 intersect(List a,List b){        List list = new ArrayList();        for (Major major : a) {            if(b.contains(major)){                list.add(major);            }        }        return list;    }}class StrategyB {    public List intersect(List a,List 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 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 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.javaxl.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 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 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 intersect(List a, List b);}public class StrategyA implements Strategy{    public List intersect(List a,List b){        List list = new ArrayList();        for (Major major : a) {            if(b.contains(major)){                list.add(major);            }        }        return list;    }}public class Context {    public List intersect(List a, List 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 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 intersect2 = context.intersect(a.list, b.list, new Strategy() {            @Override            public List intersect(List a, List 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策略接口的使用

    • JDBC对Result结果集的处理

  • 角色

  • 案例

  • 注意事项和细节

  • 应用

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/826180.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号