状态模式&责任链模式&观察者模式&策略模式

状态模式&责任链模式&观察者模式&策略模式,第1张

状态模式(State)

角色

Context:环境角色:用于维护 State 实例,这个实例定义当前状态

State:抽象状态角色:聚合到Context环境角色中

ConcreteState :具体的状态角色 ConcreteStateA ConcreteStateB ConcreteStateC

UML类图

 案例:抽奖活动项目设计

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个,代码已经比较复杂了;状态越多,代码嵌套就越复杂,维护成本就越高;

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)

角色

Handler 抽象的处理者, 定义了一个处理请求的接口

ConcreteHandlerA , B 具体的处理者, 处理它自己负责的请求, 可以访问它的后继者(即下一个处理者)

Request 含义很多属性,表示一个请求

案例

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

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

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

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

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

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

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 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 气象局 WeatherData

UML类图  

案例

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

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

运行结果为:

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),包括注册,移除和通知

策略模式(Strategy)

 

角色

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

案例

需求:学院共有专业需求

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

运行结果为:

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 改变它,使它易于切换、易于理解、易于扩展

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

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/723145.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存