行为型模式有哪些内容

2023-05-23

本篇内容主要讲解“行为型模式有哪些内容”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“行为型模式有哪些内容”吧!

责任链模式

责任链模式可以拆分为责任和链,责任是指有责任去干嘛,链可以参考链表嘛,有下一级。

场景:现在你是某公司的员工,拿到了一个比较紧急的文件(文件的紧急性肯定不一样嘛),需要更高一层的领导来处理下文件。

普通模式

文件类:

public class File {

    private FileClass fileClass;	//文件的重要等级
    private String content;			//文件的内容

    //省略

}

//枚举类表示文件的重要等级
enum FileClass {
    NORMAL,
    IMPORTANT,
    EMERGENCY
}

员工接口:

public interface IStaff {
    //获取员工的名字
    public String getName();
    
    //获取要处理文件的等级
    public FileClass getFileClass();
    
    //获取员工的需求
    public String getRequest();    
}

员工:

public class Staff implements IStaff {
    private File file;
    private String name;

	//省略构造函数

    @Override
    public String getName() {
        return name;
    }

    @Override
    public FileClass getFileClass() {
        return file.getFileClass();
    }

    @Override
    public String getRequest() {
        return "这份文件【" + file.getContent() +"】需要处理下";
    }
}

领导接口:

public interface IHandler {
    //处理文件
    public void handle(IStaff staff);
}

组长:

public class Leader implements IHandler {
    @Override
    public void handle(IStaff staff) {
        System.out.println(staff.getName() + ": " + staff.getRequest());
        System.out.println("组长:现在处理");
    }
}

总监:

public class Director implements IHandler{
    @Override
    public void handle(IStaff staff) {
        System.out.println(staff.getName() + ": " + staff.getRequest());
        System.out.println("总监:现在处理");
    }
}

主管:

public class Supervisor implements IHandler {
    @Override
    public void handle(IStaff staff) {
        System.out.println(staff.getName() + ": " + staff.getRequest());
        System.out.println("主管:现在处理");
    }
}

Client:

public class Client {
    public static void main(String[] args) {
        File file = new File(FileClass.IMPORTANT, "策划方案");
        IStaff staff = new Staff(file, "imperfect");
        
        if(file.getFileClass().equals(FileClass.NORMAL)) {
            new Leader().handle(staff);
        } else if(file.getFileClass().equals(FileClass.IMPORTANT)) {
            new Director().handle(staff);
        } else if(file.getFileClass().equals(FileClass.EMERGENCY)) {
            new Supervisor().handle(staff);
        } else {
            System.out.println("权限不够");
        }
        
    }
}

你瞅瞅,仔细品,这一堆if else直接在Client类给暴露出来了,而且是在Client中才进行判断不同等级给不同的领导处理。

通俗地比喻呢,就是员工拿到了文件后,把自己的组长,总监,主管全都叫到自己跟前,然后说,这份文件是比较重要的,给你们谁处理才有权限。确实是可以完成人物,但是这样的方式现实吗?

接近现实的一种方式是怎么样的呢,员工拿到文件后,首先给自己的直接领导组长,在领导层(handler)中的最低的一层(链头)。接着组长再看自己有没有责任去处理文件,没有的话再给下一层来处理,这就是责任链模式

责任链模式

文件类和员工类不变,主要是领导层(handler)的变化。

抽象领导类:

public abstract class AbstractHandler {
    private FileClass fileClass;
    private AbstractHandler nextHandler;
    private String name;

    //在类构造的时候就明确了职责
    //就像你入职就知道自己的责任是处理什么文件
    public AbstractHandler(FileClass fileClass, String name) {
        this.fileClass = fileClass;
        this.name = name;
    }

    //取得领导的名字
    public String getName() {
        return name;
    }

    //没有责任,交给下一级
    public void setNextHandler(AbstractHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    //处理回应,每个人的回应方式不一样,所以抽象出来
    public abstract void respond(IStaff staff);

    //处理信息
    public void handle(IStaff staff) {
        if(fileClass.equals(staff.getFileClass())) {
            respond(staff);
        } else {
            if(nextHandler != null) {
                nextHandler.respond(staff);
            } else {
                System.out.println("已经到最高权限!!!");
            }
        }
    }

}

组长:

public class Leader extends AbstractHandler {

    public Leader(String name) {
        super(FileClass.NORMAL, name);
    }

    @Override
    public void respond(IStaff staff) {
        System.out.println(staff.getName() + ": " + staff.getRequest());
        System.out.println(getName() + "组长:做出了回应");
    }
}

总监:

public class Director extends AbstractHandler{

    public Director(String name) {
        super(FileClass.IMPORTANT, name);
    }

    @Override
    public void respond(IStaff staff) {
        System.out.println(staff.getName() + ": " + staff.getRequest());
        System.out.println(getName() + "总监:做出了回应");
    }
}

主管:

public class Supervisor extends AbstractHandler {

    public Supervisor(String name) {
        super(FileClass.EMERGENCY, name);
    }

    @Override
    public void respond(IStaff staff) {
        System.out.println(staff.getName() + ": " + staff.getRequest());
        System.out.println(getName() + "主管:做出了回应");
    }
}

Client:

public class Client {
    public static void main(String[] args) {
        File file = new File(FileClass.IMPORTANT, "营销方案");
        IStaff staff = new Staff(file, "imperfect");

        //创建领导层
        AbstractHandler leader = new Leader("leaderWu");
        AbstractHandler director = new Director("directorWu");
        AbstractHandler supervisor = new Supervisor("supervisorWu");

        //设置层级关系,跟链表类似
        leader.setNextHandler(director);
        director.setNextHandler(supervisor);

        //首先交给直接领导处理
        leader.handle(staff);
        
    }
}

优缺点

  • **优点:**处理和请求分开,员工不知道最终文件是谁处理的

  • **缺点:**缺点也十分明显,如果责任链很长,而处理者刚好在最后,是不是要遍历完责任链。这样性能就比较低,在实际使用中,一般会折这一个最大链长来保证性能。

UML类图

命令模式

命令模式,一句话就是给你一个命令,必须要遵守并且执行,有点像是军队里面“服从命令是军人的天职”。

不知道大学有没有参加过数学建模,反正我是没有参加过,但是有了解过一般构成,一个小队里面一般有主要负责搜索的同学,写代码的同学,写论文的同学和指导老师

普通模式

抽象成员类(receiver):

public abstract class NTeammate {

    public abstract void changeRequire();

    public abstract void modify();

    public abstract void work();

}

Searcher:

public class NSearcher extends NTeammate {
    @Override
    public void changeRequire() {
        System.out.println("searcher 了解到需求改变");
    }

    @Override
    public void modify() {

    }

    @Override
    public void work() {
        System.out.println("searcher 开始搜索相关信息");
    }
}

Writer:

public class NWriter extends NTeammate {
    @Override
    public void changeRequire() {
        System.out.println("writer 了解到需求改变");
    }

    @Override
    public void modify() {
        System.out.println("writer 修改论文");
    }

    @Override
    public void work() {
        System.out.println("writer 开始写论文");
    }
}

Coder:

public class NCoder extends NTeammate {
    @Override
    public void changeRequire() {
        System.out.println("coder 了解到需求改变");
    }

    @Override
    public void modify() {
        System.out.println("coder 修改代码");
    }

    @Override
    public void work() {
        System.out.println("coder 开始码代码");
    }
}

Teacher:

public class NTeacher {
    public static void main(String[] args) {
        NTeammate writer = new NWriter();
        //需要改文章了
        writer.modify();
        writer.work();
    }
}

一开始,老师看到写的文展不够简洁,所以就打电话给writer,让他修改,所以就有了上面的Teacher类。这样其实还好,因为文章嘛,修改润色就好了。

过了一天,老师仔细看了下后,发现代码的算法有bug,这个漏洞导致了不仅coder要修改代码,writer也要修改相应地方的文章。

老师这下不仅要联系writer,也得联系coder,那么Teacher类应该怎么修改呢?

public class NTeacher {
    public static void main(String[] args) {
        NTeammate writer = new NWriter();
        NTeammate coder = new NCoder();
        //需要改bug和文章了
        writer.modify();
        writer.work();
        
        coder.modify();
        coder.work();
        
    }
}

可以发现,就多了一个需求,代码较之前已经有很大的改动了,这是我们不希望看到的。可能有的小伙伴会想到利用中介者模式,不过中介者模式是为了减小类和类之间的耦合,这个例子中的searcher,writer,coder并没有耦合,都在各司其职。

命令模式

如果小队里面有个队长(Invoker)就好了,可以和老师(client)沟通,不止这样,老师的指令实现起来肯定是String类型,我们可以把指令封装称一个类(command),队长只需要发布命令,命令指示队员(receiver)来做什么。这就是命令模式,队员必须执行命令要求做的。

抽象队员以及具体队员还是和上面一样,这里就不再赘述。

抽象命令类:

public abstract class AbstractCommand {
    protected Coder coder = new Coder();
    protected Searcher searcher = new Searcher();
    protected Writer writer = new Writer();
    
    //一定要有个执行的方法,下达一个命令
    public abstract void execute();
}

具体命令类(Command):

有哪些命令,都可以封装起来

改变需求:

public class ChangeInfoCommand extends AbstractCommand {
    @Override
    public void execute() {
        searcher.changeRequire();
        writer.changeRequire();
        coder.changeRequire();
    }
}

修改文章:

public class ModifyArticleCommand extends AbstractCommand {
    @Override
    public void execute() {
        writer.modify();
        writer.work();
    }
}

修改代码:

public class ModifyCodeCommand extends AbstractCommand {
    @Override
    public void execute() {
        coder.modify();
        coder.work();
        writer.modify();
        writer.work();
    }
}

队长类(Invoke):

public class Captain {
    //和命令产生联系
    AbstractCommand abstractCommand;

    public Captain(AbstractCommand abstractCommand) {
        this.abstractCommand = abstractCommand;
    }

    public void invoke() {
        //发布命令要求队员进行相应的动作
        abstractCommand.execute();
    }

}

老师类(Client):

public class Teacher {
    public static void main(String[] args) {
        AbstractCommand command = new ModifyCodeCommand();
        Captain captain = new Captain(command);
        captain.invoke();
    }
}

如果老师觉得又不好了,这些怎么办呢,没有必要和成员练习,只需要提出另外一个建议,队长也不要跟队员练习,只需要发布命令,由命令指示队员去做。修改就是这么简单,一行代码的事情。

public class Teacher {
    public static void main(String[] args) {
        //AbstractCommand command = new ModifyCodeCommand();
        AbstractCommand command = new ModifyArticleCommand();
        Captain captain = new Captain(command);
        captain.invoke();
    }
}

扩展

如果说,诶,改代码的时候不仅需要修改bug和修正文章,也需要searcher来搜集信息,怎么办呢?

public class ModifyCodeCommand extends AbstractCommand {
    @Override
    public void execute() {
        searcher.work();	//只需要在具体的命令里面添加即可,客户端是完全不知道的
        coder.modify();
        coder.work();
        writer.modify();
        writer.work();
    }
}

还有一种情况就是,某些修改之后,老师发现还是之前的版本比较好,这就要求每个队员都有一个回调函数来撤销动作,返回到上一个状态,就是找到保存的之前版本的文件。只需要在抽象receiver类加一个回调函数即可

public abstract class NTeammate {

    public abstract void changeRequire();

    public abstract void modify();

    public abstract void work();
    
    //具体队友在根据自己的方式实现回调方法
    public abstract void rollback();

}

接着就是添加一个撤回命令

public class callBackCommand extends AbstractCommand {
    @Override
    public void execute() {
        //当然,需要谁撤回是可以改变的
        searcher.rollback();
        writer.rollback();
        coder.rollback();
    }
}

UML类图

解释器模式

这个无论是工作上还是学习中都是比较冷门的设计模式。解释器模式由以下类组成

  • Context: Context用于封装解释器的全局信息,所有具体的解释器均需要访问Context。

  • AbstractExpression: 一个抽象类或接口,声明执行的解释方法,由所有具体的解释器实现

  • TerminalExpression: 一种解释器类,实现与语法的终结符相关的操作。终结符表达式必须终结被实现和实例化,因为它表示表达式的结尾。

  • NonTerminalExpreesion: 这是实现语法的不同规则或符号的类。对于每一种语法都应该创建一个类。

这个东西解释起来比较拗口,一时也没有很好的通俗的解释,那就直接看例子叭。

AbstractExpression

public interface Expression {
    public float interpret();
}

TerminalExpression

public class Number implements Expression{
    private final float number;

    public Number(float number) {
        this.number = number;
    }

    @Override
    public float interpret() {
        return number;
    }
}

还记得之前说过的流吗,TerminalExpression 就类似终结操作,而NonTerminalExpression 就是类似中间操作

NonTerminalExpression

public class Plus implements Expression{
    Expression left;
    Expression right;

    public Plus(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public float interpret() {
        return left.interpret() + right.interpret();
    }
}

注意对于每一个语法都要有一个独立的类

public class Minus implements Expression {
    Expression left;
    Expression right;

    public Minus(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public float interpret() {
        return left.interpret() - right.interpret();
    }
}

Context

public class Evaluator {

    public static void main(String[] args) {
        Evaluator evaluator = new Evaluator();
        System.out.println(evaluator.evaluate("3 4 +"));
        System.out.println(evaluator.evaluate("4 3 -"));
        System.out.println(evaluator.evaluate("4 3 - 2 +"));
    }


    public float evaluate(String expression) {
        Stack<Expression> stack = new Stack<>();
        float result = 0;
        for (String token : expression.split(" ")) {
            Expression exp = null;
            if (isOperator(token)) {
                if (token.equals("+")) {
                    exp = stack.push(new Plus(stack.pop(), stack.pop()));
                } else if (token.equals("-")) {
                    exp = stack.push(new Minus(stack.pop(), stack.pop()));
                }

                if (null != exp) {
                    result = exp.interpret();
                    stack.push(new Number(result));
                }
            }

            if (isNumber(token)) {
                stack.push(new Number(Float.parseFloat(token)));
            }
        }
        return result;
    }

    private boolean isNumber(String token) {
        try {
            Float.parseFloat(token);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    private boolean isOperator(String token) {
        return token.equals("+") || token.equals("-");
    }
    
}

UML类图

到此,相信大家对“行为型模式有哪些内容”有了更深的了解,不妨来实际操作一番吧!这里是本站网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

《行为型模式有哪些内容.doc》

下载本文的Word格式文档,以方便收藏与打印。