行为型模式

news2024/11/14 2:15:55

1.模版方法

  • 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤

  • 结构

    • 抽象类:负责给出一个轮廓与骨架,由一个模版方法和若干个基本方法构成

      • 模版方法:按某种顺序调用其包含的基本方法
      • 基本方法:实现的每个步骤,基本方法又可以分为三种
        • 抽象方法:一个抽象方法由抽象类声明,由具体子类实现
        • 具体方法:一个具体方法由抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承
        • 钩子方法:抽象类中可以实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。一般钩子方法是用于判断的逻辑方法,这类方法名一般为isXxx,返回值类型为boolean
    • 具体子类:实现抽象类中所定义的抽象方法和钩子方法,它是一个顶级逻辑的组成步骤

      image-20230117165307085

  • 实现

    public abstract class AbstractClass {
    
        public void cookProcess(){
           pourOil();
           heatOil();
           pourVegetable();
           pourSauce();
           fry();
        }
        public void pourOil(){
            System.out.println("倒油");
        }
        public void heatOil(){
            System.out.println("热油");
        }
        public abstract void pourVegetable();
        public abstract void pourSauce();
    
        public void fry(){
            System.out.println("一直翻炒");
        }
    }
    
    public class ConCreateClassBaoCai extends AbstractClass{
        @Override
        public void pourVegetable() {
            System.out.println("爆炒包菜");
        }
    
        @Override
        public void pourSauce() {
            System.out.println("放入小辣椒");
        }
    }
    
  • 优缺点

    • 优点
      • 仅允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小
      • 可将重复代码提取到一个超类中
    • 缺点
      • 部分客户端可能会受到算法框架的限制
      • 通过子类抑制默认步骤实现可能会导致违反里氏替换原则
      • 模板方法中的步骤越多, 其维护工作就可能会越困难

2.策略模式

  • 定义一系列算法,并将算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户,策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的虚i昂对这些算法进行管理

  • 结构

    • 抽象策略:由一个接口或抽象类实现,此角色给出所有的具体策略类所需的接口

    • 具体策略:实现抽象策略定义的接口,提供具体的算法实现行为

    • 环境类:持有一个策略类的引用,最终给客户端调用

      image-20230117202956528

  • 实现

    public interface Strategy {
    
        void show();
    }
    
    public class StrategyA implements Strategy{
        @Override
        public void show() {
            System.out.println("买一送一");
        }
    }
    
    public class SalesMan {
        private Strategy strategy;
    
        public SalesMan(Strategy strategy) {
            this.strategy = strategy;
        }
    
        public void salesManShow(){
            strategy.show();
        }
    }
    
  • 优缺点

    • 优点
      • 运行时切换对象内的算法
      • 将算法的实现和使用算法的代码隔离开来
      • 使用组合来代替继承
      • 开闭原则, 你无需对上下文进行修改就能够引入新的策略
    • 缺点
      • 如果你的算法极少发生改变, 那么没有任何理由引入新的类和接口。 使用该模式只会让程序过于复杂
      • 客户端必须知晓策略间的不同——它需要选择合适的策略

3.命令模式

  • 将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储、投递、调用、增加与管理

  • 结构

    • 抽象命令类:定义命令的接口,声明执行的方法

    • 具体命令类:具体的命令,实现命令接口,通常会持有接受者,并调用接受者的功能来完成命令要执行的操作

    • 实现者/接收者:接收者,真正执行命令的对象,任何类斗可能成为一个接收者,只要它能够实现命令要求实现的相对功能

    • 调用者/请求者:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象,这个是客户端真正触发命令并要求命令执行相对应的操作的地方,也就是说相当于使用命令对象的入口

      image-20230117212836742

  • 实现

    @Data
    public class Order {
        private int dingingTable;
        private Map<String,Integer> foodDic = new HashMap<>();
    
        public void setFoodDic(String name ,int num) {
            foodDic.put(name,num);
        }
    }
    
    // 实现者/接收者
    public class SeniorChef {
    
        public void makeFood(int num, String foodName) {
            System.out.println(num + "份," + foodName);
        }
    }
    
    // 抽象命令类
    public interface Command {
         void execute();
    }
    
    // 具体命令类
    public class OrderCommand implements Command {
    
        private SeniorChef receiver;
        private Order order;
    
        public OrderCommand(SeniorChef receiver, Order order) {
            this.receiver = receiver;
            this.order = order;
        }
    
        @Override
        public void execute() {
            System.out.println(order.getDingingTable() + "桌的订单");
            Map<String, Integer> foodDic = order.getFoodDic();
            Set<String> keys = foodDic.keySet();
            for (String key : keys) {
                receiver.makeFood(foodDic.get(key), key);
            }
            System.out.println(order.getDingingTable() + "桌的饭准备完毕");
        }
    }
    
    // 调用者/请求者
    public class Waiter {
        private List<Command> commands  = new ArrayList<>();
    
        public void  setCommand(Command command) {
            commands.add(command);
        }
    
        public void orderUp(){
            System.out.println("服务员,您有新的订单");
            for (Command command : commands) {
                command.execute();
            }
        }
    }
    
  • 优缺点

    • 优点
      • 单一职责原则。 你可以解耦触发和执行操作的类
      • 开闭原则。 你可以在不修改已有客户端代码的情况下在程序中创建新的命令
      • 可以实现撤销和恢复功能
      • 可以实现操作的延迟执行
      • 可以将一组简单命令组合成一个复杂命令
    • 缺点
      • 代码可能会变得更加复杂, 因为你在发送者和接收者之间增加了一个全新的层次

4.责任链模式

  • 避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链,当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止

  • 结构

    • 抽象处理器:定义一个处理请求的接口,包含抽象处理方法和一个后继连接

    • 具体处理器:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后续者

    • 客户类:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程

      image-20230117231209821

  • 实现

    // 抽象处理器
    public abstract class Handler {
        protected static final int NUM_ONE = 1;
        protected static final int NUM_THREE = 3;
        protected static final int NUM_SEVEN = 7;
    
        private int numStart ;
        private int numEnd;
        private Handler nextHandler;
    
        public Handler(int numStart, int numEnd) {
            this.numStart = numStart;
            this.numEnd = numEnd;
        }
    
        public void setNextHandler(Handler nextHandler) {
            this.nextHandler = nextHandler;
        }
    
        public abstract void submit(LeaveRequest leave);
    
        public void handleLeave(LeaveRequest leave){
            this.submit(leave);
            if (this.nextHandler != null && leave.getNum() > this.numEnd){
                this.nextHandler.handleLeave(leave);
            }else {
                System.out.println("异常");
            }
        }
    }
    // 具体处理器
    public class GroupLeader extends Handler{
        public GroupLeader() {
            super(0,NUM_ONE);
        }
    
        @Override
        public void submit(LeaveRequest leave) {
            System.out.println(leave.getName() + "请假" + leave.getNum() + "天" + leave.getContent() + "。");
            System.out.println("小组长审批通过");
        }
    }
    
    @Data
    public class LeaveRequest {
        private String name;
        private int num;
        private String content;
    
        public LeaveRequest(String name, int num, String content) {
            this.name = name;
            this.num = num;
            this.content = content;
        }
    }
    
    // 客户类
    public class TestChain {
        public static void main(String[] args) {
            LeaveRequest request = new LeaveRequest("张三",8,"身体不适");
            GroupLeader groupLeader = new GroupLeader();
            Manager manager = new Manager();
            GeneralManager generalManager = new GeneralManager();
    
            groupLeader.setNextHandler(manager);
            manager.setNextHandler(generalManager);
            groupLeader.handleLeave(request);
        }
    }
    
  • 优缺点

    • 优点
      • 可以控制请求处理的顺序
      • 单一职责原则。 你可对发起操作和执行操作的类进行解耦
      • 开闭原则。 你可以在不更改现有代码的情况下在程序中新增处理者
    • 缺点
      • 部分请求可能未被处理

5.状态模式

  • 对有状态的对象,把复杂的判断逻辑提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为

  • 结构

    • 环境角色:定义客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理

    • 抽象状态:定义一个接口,用以封装环境对象中的特定状态所对应的行为

    • 具体状态:实现抽象状态所对应的行为

      image-20230118145310882

  • 实现

    // 抽象状态
    public abstract class LiftState {
        protected Context context;
    
        public void setContext(Context context) {
            this.context = context;
        }
    
        public abstract void open();
    
        public abstract void close();
    
        public abstract void stop();
    
        public abstract void run();
    }
    // 环境角色
    public class Context {
    
        public final static OpenNingState OPEN_NING_STATE = new OpenNingState();
        public final static ClosingState CLOSING_STATE = new ClosingState();
        public final static RunNingState RUN_NING_STATE = new RunNingState();
        public final static StopPingState STOP_PING_STATE = new StopPingState();
    
    
        private LiftState liftState;
    
        public void setLiftState(LiftState liftState) {
            this.liftState = liftState;
            liftState.setContext(this);
        }
    
        public void open() {
            liftState.open();
        }
    
        public void close() {
            liftState.close();
        }
    
        public void stop() {
            liftState.stop();
        }
    
        public void run() {
            liftState.run();
        }
    }
    // 具体状态
    public class RunNingState extends LiftState{
        @Override
        public void open() {
    
        }
    
        @Override
        public void close() {
    
        }
    
        @Override
        public void stop() {
            super.context.setLiftState(Context.STOP_PING_STATE);
            super.context.stop();
        }
    
        @Override
        public void run() {
            System.out.println("电梯正在运行");
        }
    }
    
  • 优缺点

    • 优点
      • 单一职责原则, 将与特定状态相关的代码放在单独的类中
      • 开闭原则,无需修改已有状态类和上下文就能引入新状态
      • 通过消除臃肿的状态机条件语句简化上下文代码
    • 缺点
      • 如果状态机只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作

6.观察者模式

  • 定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态变化时,会通知所有观察者对象,使他们能够自动更新自已

  • 结构

    • 抽象主题:抽象主题角色能把所有观察者保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象

    • 具体主题:该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知

    • 抽象观察者:观察者的抽象类,定义了一个更新接口,使得在得到主题更改通知时更新自已

    • 具体观察者:实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自已的状态

      image-20230118154242345

  • 实现

    // 抽象观察者
    public interface Observer {
        void update(String msg);
    }
    
    // 具体主题
    public class WxUserObserver implements Observer {
        private String name;
    
        public WxUserObserver(String name) {
            this.name = name;
        }
    
        @Override
        public void update(String msg) {
            System.out.println(name + "接收到消息:" + msg);
        }
    }
    
    // 抽象观察者
    public interface Subject {
    
        void attach(Observer observer);
        void detach(Observer observer);
        void notifyMsg(String msg);
    }
    
    // 具体观察者
    public class SubscriptionSubject implements Subject {
        private List<Observer> observerList = new ArrayList<>();
    
    
        @Override
        public void attach(Observer observer) {
            observerList.add(observer);
        }
    
        @Override
        public void detach(Observer observer) {
            observerList.remove(observer);
        }
    
        @Override
        public void notifyMsg(String msg) {
            for (Observer observer : observerList) {
                observer.update(msg);
            }
        }
    }
    
  • 优缺点

    • 优点
      • 可以在运行时建立对象之间的联系
      • 开闭原则,你无需修改发布者代码就能引入新的订阅者类 (如果是发布者接口则可轻松引入发布者类)
    • 缺点
      • 订阅者的通知顺序是随机的

7.中介者模式

  • 定义中介角色来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互

  • 结构

    • 抽象中介者:中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法

    • 具体中介者:实现中介者接口,定义list来管理同事对象,协调各个同事角色之间的交互关系,因为它依赖与同事角色

    • 抽象同事类:定义同事类的接口,保存中介者对象,提供同事对象交换的抽象方法,实现所有互相影响的同事类的公共功能

    • 具体同事类:抽象同事类的实现者,当需要与其它同事对象交互时,由中介者对象负责后续的交互

      image-20230118172622055

  • 实现

    // 抽象中介者
    public abstract class Mediator {
    
        abstract void contact(String msg,Person person);
    }
    
    // 具体中介者
    @Data
    public class MediatorStructure extends Mediator{
        private HouseOwner houseOwner;
        private Tenant tenant;
    
        public void setMediatorStructure(HouseOwner houseOwner, Tenant tenant) {
            this.houseOwner = houseOwner;
            this.tenant = tenant;
        }
    
        @Override
        void contact(String msg, Person person) {
            if (person == houseOwner){
                tenant.getMessage(msg);
            }else {
                houseOwner.getMessage(msg);
            }
        }
    }
    
    // 抽象同事
    public abstract class Person {
        protected String name;
        protected Mediator mediator;
    
        public Person(String name, Mediator mediator) {
            this.name = name;
            this.mediator = mediator;
        }
    }
    // 具体同事类
    public class Tenant extends Person {
    
        public Tenant(String name, Mediator mediator) {
            super(name, mediator);
        }
    
        public void contact(String msg) {
            mediator.contact(msg, this);
        }
    
        public void getMessage(String msg) {
            System.out.println("租房者:" + name + "获取到到信息是:" + msg);
        }
    }
    
  • 优缺点

    • 优点
      • 可以减轻应用中多个组件间的耦合情况
      • 开闭原则,你无需修改实际组件就能增加新的中介者
      • 单一职责原则,以将多个组件间的交流抽取到同一位置, 使其更易于理解和维护。
    • 缺点
      • 一段时间后, 中介者可能会演化成为上帝对象

8.迭代器模式

  • 提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示

  • 结构

    • 抽象聚合:定义存储、添加、删除聚合元素以及创建迭代器对象的接口

    • 具体聚合:实现抽象聚合类,返回一个具体迭代器的实例

    • 抽象迭代器:定义访问和遍历聚合元素的接口,通常包含hasNext()、next()等方法

    • 具体迭代器:实现抽象迭代器接口中定义的方法,完成对聚合对象的遍历,记录遍历的当前位置

      image-20230118211632818

  • 实现

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Student {
        private String name ;
        private String number;
    }
    // 抽象聚合
    public interface StudentAggregate {
        void addStudent(Student student);
        void removeStudent(Student student);
        StudentIterator getStudentIterator();
    }
    
    // 具体聚合
    public class StudentAggregateImpl implements StudentAggregate{
    
        private List<Student> studentList = new ArrayList<>();
        @Override
        public void addStudent(Student student) {
            studentList.add(student);
        }
    
        @Override
        public void removeStudent(Student student) {
            studentList.remove(student);
        }
    
        @Override
        public StudentIterator getStudentIterator() {
            return new StudentIteratorImpl(studentList);
        }
    }
    
    // 抽象迭代器
    public interface StudentIterator {
        boolean hasNext();
    
        Student next();
    }
    
    // 具体迭代器
    public class StudentIteratorImpl implements StudentIterator {
        private List<Student> students;
        private int position = 0;
    
        public StudentIteratorImpl(List<Student> students) {
            this.students = students;
        }
    
        @Override
        public boolean hasNext() {
            return position < students.size();
        }
    
        @Override
        public Student next() {
            return students.get(position++);
        }
    }
    
  • 优缺点

    • 优点
      • 单一职责原则,通过将体积庞大的遍历算法代码抽取为独立的类, 你可对客户端代码和集合进行整理
      • 开闭原则, 你可实现新型的集合和迭代器并将其传递给现有代码, 无需修改现有代码
      • 你可以并行遍历同一集合, 因为每个迭代器对象都包含其自身的遍历状态
    • 缺点
      • 程序只与简单的集合进行交互, 应用该模式可能会矫枉过正。
      • 对于某些特殊集合, 使用迭代器可能比直接遍历的效率低。

9.访问者模式

  • 封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数就结构的前提下定义作用于这些元素的新的操作

  • 结构

    • 抽象访问者:定义了对每个元素访问的行为,它的参数就是可以访问的元素,它的方法个数理论上来讲与元素类个数是一样的,访问者模式要求元素类的个数不能改变

    • 具体访问者:给出对每一个元素类访问时所产生的具体行为

    • 抽象元素:定义了一个接受访问者的方法,其意义是指,每一个元素都要可以被访问者访问

    • 具体元素:提供接受访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法

    • 对象结构:定义当中所提到的对象结构,对象结构上一个抽象表述,具体点可以理解为一个具有容器性质或者复合对象特性的类,它含有一组元素,并且可以迭代这些元素,供访问者访问

      image-20230118221031929

  • 实现

    // 抽象元素
    public interface Animal {
    
        void accept(Person person);
    }
    
    // 具体元素
    public class Cat implements Animal{
        @Override
        public void accept(Person person) {
            person.feed(this);
            System.out.println("喵喵喵~~~");
        }
    }
    
    // 抽象访问者
    public interface Person {
    
        void feed(Cat cat);
    
        void feed(Dog dog);
    
    }
    
    // 具体访问者
    public class Someone implements Person {
        @Override
        public void feed(Cat cat) {
            System.out.println("其它人喂猫");
        }
    
        @Override
        public void feed(Dog dog) {
            System.out.println("其它人喂狗");
        }
    }
    
    // 结构对象
    public class Home {
    
        private List<Animal> nodeList = new ArrayList<>();
    
        public void action(Person person) {
            for (Animal animal : nodeList) {
                animal.accept(person);
            }
        }
    
    
        public void add(Animal animal) {
            nodeList.add(animal);
        }
    }
    
  • 优缺点

    • 优点
      • 开闭原则。 你可以引入在不同类对象上执行的新行为, 且无需对这些类做出修改
      • 单一职责原则。 可将同一行为的不同版本移到同一个类中
    • 缺点
      • 每次在元素层次结构中添加或移除一个类时, 你都要更新所有的访问者。
      • 在访问者同某个元素进行交互时, 它们可能没有访问元素私有成员变量和方法的必要权限

10.备忘录模式

  • 又叫快照模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态

  • 结构

    • 发起人:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其它业务功能,它可以访问备忘录的所有信息
    • 备忘录:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人,备忘录有两个等效的接口
      • 窄接口:管理者对象(和其它发起人对象之外的任务对象)看到的是备忘录的窄接口,这个窄接口只允许他把备忘录对象传给其它的对象
      • 宽接口:与管理者看到的窄接口相反,发起人对象可以看到一个宽接口,这个宽接口允许它读取所有的数据,以便根据这些数据恢复这个发起人对象的内部状态
    • 管理者:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能堆备忘录的内容进行访问与修改
  • 白箱备忘录模式

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class WhiteRoleStateMemento {
        private int vit;
        private int atk;
        private int def;
    
    }
    
    public class WhiteRoleStateCaretaker {
        private WhiteRoleStateMemento roleStateMemento;
    
        public WhiteRoleStateMemento getRoleStateMemento() {
            return roleStateMemento;
        }
    
        public void setRoleStateMemento(WhiteRoleStateMemento roleStateMemento) {
            this.roleStateMemento = roleStateMemento;
        }
    }
    
    public class WhiteGameRole {
        private int vit;
        private int atk;
        private int def;
    
        public void initState() {
            this.vit = 100;
            this.atk = 100;
            this.def = 100;
        }
    
        public void fight() {
            this.vit = 0;
            this.atk = 0;
            this.def = 0;
        }
    
        public WhiteRoleStateMemento saveState() {
            return new WhiteRoleStateMemento(vit, atk, def);
        }
    
        public void recoverState(WhiteRoleStateMemento roleStateMemento) {
            this.vit = roleStateMemento.getVit();
            this.atk = roleStateMemento.getAtk();
            this.def = roleStateMemento.getDef();
        }
    
        public void stateDisplay() {
            System.out.println("角色生命力:" + vit);
            System.out.println("角色攻击力:" + atk);
            System.out.println("角色防御力:" + def);
        }
    
    }
    

    image-20230123151052445

  • 黑箱备忘录模式

    public interface BlackMemento {
    }
    
    public class BlackRoleStateCaretaker {
        private BlackMemento blackMemento;
    
        public BlackMemento getBlackMemento() {
            return blackMemento;
        }
    
        public void setBlackMemento(BlackMemento blackMemento) {
            this.blackMemento = blackMemento;
        }
    }
    
    public class BlackGameRole {
        private int vit;
        private int atk;
        private int def;
    
        public void initState() {
            this.vit = 100;
            this.atk = 100;
            this.def = 100;
        }
    
        public void fight() {
            this.vit = 0;
            this.atk = 0;
            this.def = 0;
        }
    
        public BlackMemento saveState() {
            return new RoleStateMemento(vit, atk, def);
        }
    
        public void recoverState(BlackMemento blackMemento) {
            RoleStateMemento roleStateMemento = (RoleStateMemento) blackMemento;
            this.vit = roleStateMemento.getVit();
            this.atk = roleStateMemento.getAtk();
            this.def = roleStateMemento.getDef();
        }
    
        public void stateDisplay() {
            System.out.println("角色生命力:" + vit);
            System.out.println("角色攻击力:" + atk);
            System.out.println("角色防御力:" + def);
        }
    
    
        @AllArgsConstructor
        @NoArgsConstructor
        @Data
        private class RoleStateMemento implements BlackMemento {
            private int vit;
            private int atk;
            private int def;
        }
    }
    

    image-20230123151323849

11.解释器模式

  • 给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子

  • 结构

    • 抽象表达式:定义解释器的接口,约定解释器的解释操作,主要包含解释方法

    • 终结者表达式:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应

    • 非终结符表达式:抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于非终结符表达式

    • 环境角色:包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值

    • 客户端:任务是将需要分析的句子或者表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方式,也可以通过环境角色间接访问解释器的解释方法

      image-20230123162618106

  • 实现

    public abstract class AbstractExpression {
    
        public abstract int interpret(Context context);
    }
    
    public class Context {
    
        private Map<Variable,Integer> map = new HashMap<>();
    
        public void assign(Variable var ,Integer value){
            map.put(var,value);
        }
    
        public int getValue(Variable var){
            return map.get(var);
        }
    }
    
    public class Variable extends AbstractExpression {
        private String name;
    
        public Variable(String name) {
            this.name = name;
        }
    
        @Override
        public int interpret(Context context) {
            return context.getValue(this);
        }
    
        @Override
        public String toString() {
            return name;
        }
    }
    
    public class Plus extends AbstractExpression{
        private AbstractExpression left;
        private AbstractExpression right;
    
    
        public Plus(AbstractExpression left, AbstractExpression right) {
            this.left = left;
            this.right = right;
        }
    
        public int interpret(Context context) {
            return left.interpret(context) + right.interpret(context);
        }
    
        @Override
        public String toString() {
            return "(" + left.toString() + "+" + right.toString() + ")";
        }
    }
    
    public class Minus extends AbstractExpression{
        private AbstractExpression left;
        private AbstractExpression right;
    
    
        public Minus(AbstractExpression left, AbstractExpression right) {
            this.left = left;
            this.right = right;
        }
    
        public int interpret(Context context) {
            return left.interpret(context) - right.interpret(context);
        }
    
        @Override
        public String toString() {
            return "(" + left.toString() + "-" + right.toString() + ")";
        }
    }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/176825.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机视觉OpenCv学习系列:第八部分、图像操作-4

第八部分、图像操作-4第一节、图像卷积操作1.图像卷积定义2.卷积函数3.代码练习与测试第二节、高斯模糊1.高斯模糊2.函数解释3.代码练习与测试第三节、像素重映射1.像素重映射定义2.重映射函数3.代码练习与测试学习参考第一节、图像卷积操作 1.图像卷积定义 卷积的基本原理&am…

java spring IOC xml 方式 内部Bean注入

上次说了外部 Bean注入 这次来演示一个内部的 Bean注入 我们先创建一个spring 项目 导入最基本的 spring 包 在项目src目录下创建一个包 cascade cascade包下创建两个类 Dept 部门类 参考代码如下 package cascade;//部门类 public class Dept {private String dname;publi…

windows ssdt

前言 我们 ring 3 跳转 ring0 另一种方式使用sysenter命令。 sysenter 相比起jmp,int xx方式相比速度更快&#xff0c;因为sysenter指令大量的使用了MSR寄存器 存储跳转地址等。 MSR寄存器相关读/写命令 //读取msr寄存器 rdmsr xxxx //写入msr寄存器 wrmsr xxxx其中xxx是ms…

轻量实时操作系统学习(一)

306xH系列产品基于高性能RISC-V CPU核&#xff0c;工作频率最高到200MHz&#xff0c;集成了FPU浮点处理单元&#xff0c;支持浮点乘法&#xff0c;支持浮点乘法&#xff0c;除法和开方等复杂数学运算指令&#xff0c;支持16KB的SRAM和最高160KB的flash存储单元。 该MCU集成最多…

【My Electronic Notes系列——二极管】

目录 序言&#xff1a; &#x1f3ee;&#x1f3ee;新年的钟声响&#xff0c;新年的脚步迈&#xff0c;祝新年的钟声&#xff0c;敲响你心中快乐的音符&#xff0c;幸运与平安&#xff0c;如春天的脚步紧紧相随&#xff0c;春节快乐&#xff01;春华秋实&#xff0c;我永远与…

【目标检测论文解读复现NO.25】基于改进Yolov5的地铁隧道附属设施与衬砌表观病害检测方法

前言 此前出了目标改进算法专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读最新目标检测算法论文&#xff0c…

【Unity Shader 赛博小人01】UV准备 SD制作特效贴图

写在前面 Unity 卡通渲染 程序化天空盒提到了——“再整个uv1将云片平铺&#xff0c;将uv1对应到世界坐标x轴旋转角、y轴旋转角&#xff0c;消散信息放到顶点色。”&#xff0c;就是这句话&#xff01;我又遇到了几个问题&#xff08;本菜鸡不知道的东西太多太多了&#xff09…

Spring的使用

开篇点题&#xff1a;为什么要用到Spring&#xff1f;参考这篇文章&#xff1a;http://t.csdn.cn/oR5lM一、创建一个Maven项目1.创建一个Maven项目2.添加Spring依赖/框架支持在pom.xml中添加框架的支持&#xff0c;xml配置如下&#xff1a;&#xff08;下载失败参考&#xff1a…

设计模式_自定义Spring框架(IOC)

设计模式_自定义Spring框架&#xff08;IOC&#xff09; 笔记整理自 黑马程序员Java设计模式详解&#xff0c; 23种Java设计模式&#xff08;图解框架源码分析实战&#xff09; Spring使用回顾 自定义spring 框架前&#xff0c;先回顾一下 Spring 框架的使用&#xff0c;从而分…

acwing基础课——快速幂

由数据范围反推算法复杂度以及算法内容 - AcWing 常用代码模板4——数学知识 - AcWing 基本思想&#xff1a; 求一个数的n次时&#xff0c;我们的时间复杂度为O(n),当n特别大时&#xff0c;效率会很低可能超时&#xff0c;此时我们就需要运用到快速幂&#xff0c;将我们的时间…

基于PHP和MySQL的新闻发布系统——【功能优化】

前言 2023年第一篇文章&#xff0c;祝大家在新的一年里“卯”足干劲&#xff0c;在技术上 “兔”飞猛进&#xff01; 上一篇文章 基于PHP和MySQL的新闻发布系统 给大家介绍了制作一个新闻发布系统的主要功能的实现&#xff0c;在文章的末尾还提出了一些需要完善的方面。那么…

Vue3【style-scoped、style-module、类和内联样式、props、练习】

文章目录style-scopedstyle-module类和内联样式props练习style-scoped 可以直接通过style标签来编写样式&#xff0c; 如果直接通过style标签写样式&#xff0c;此时编写的样式是全局样式会影响到所有的组件 可以为style标签添加一个scoped属性&#xff0c;这样样式将成为局部…

为什么会有右值引用?(移动构造、移动赋值)

目录 1、左值引用的缺陷 2、移动构造&#xff1a;解决临时对象的深拷贝 3、拓展&#xff1a;移动赋值 1、左值引用的缺陷 左值引用作为函数参数传递&#xff0c;减少了参数拷贝&#xff1b;但是作为函数返回值&#xff0c;并不适用于所有场景&#xff0c;比如要返回一个临…

Linux——innode

目录 回顾缓冲区 标准错误流的理解 文件系统 Inode VS 文件名 创建/删除/查看文件系统做了什么 软硬链接 动静态库 习题 回顾缓冲区 关掉1&#xff0c;log.txt中没文件是因为&#xff0c;字符串在缓冲区当中&#xff0c;缓冲区还没刷新&#xff0c;我们把fd给关了…

堆的实现及应用

下面用C语言介绍堆的实现以及应用 文章目录1. 堆的简介2. 堆的实现HeapInitHeapDestroyHeapPushHeapPop3. 堆的应用堆排序TopK问题1. 堆的简介 堆是一颗完全二叉树。这里所说的堆是一种非连续的数据结构&#xff0c;与操作系统内存分布的堆是两回事&#xff0c;它们没有任何联…

金融帝国实验室(Capitalism Lab)官方中文汉化包下载(v4.03)

<FCT汉化小组>Vol.001号作品 ————————————— ◎作品名称&#xff1a;金融帝国实验室&#xff08;CapLab&#xff09;官方汉化包 ◎汉化作者&#xff1a;FCT汉化小组&#xff08;Enlight Software认证&#xff09; ◎发布版本&#xff1a;CapLab Simplifi…

POJ 1845 Sumdiv题解(C++ 整数惟一分解定理+分治法求等比数列之和+快速幂)

文章目录整数惟一分解定理分治法求等比数列和完整代码传送门&#xff1a; POJ 1845 SumDiv 整数惟一分解定理 任何一个大于1的整数n都可以分解成若干个质因数&#xff08;素因数&#xff09;的连乘积&#xff0c;如果不计各个素因数的顺序&#xff0c;那么这种分解是唯一的&a…

王者荣耀入门技能树

前言 最近在学习技能树&#xff0c;我也试着写一写技能树&#xff0c;放松一下。 这里附上一张可爱的兔兔应景。仔细看&#xff0c;后边题目会提到&#xff0c;哈哈。 职业 以下哪个不属于王者荣耀中的职业&#xff1a; 射手法师辅助亚瑟 技能 以下哪个技能可以加快打野…

春节假期后,如何快速让员工恢复上班的元气和状态?

每当假期过后&#xff0c;总有一些员工无法快速恢复工作状态&#xff0c;团队的氛围也很难一下子热起来。而春节假期既是长假&#xff0c;又是过节氛围最浓厚的假期&#xff0c;节后返工的涣散问题自然更明显一些。但对于服装店铺来说&#xff0c;年后开工正处于旺季&#xff0…

【Vue】我的尚品汇项目笔记---20230109~20230120

014之前可参考官方笔记 https://blog.csdn.net/weixin_43424325/article/details/121684101 015-axios二次封装 api/index.js 设定 //当前模块&#xff0c;API进行统一管理&#xff0c;即对请求接口统一管理 import requests from "/api/request";//首页三级分类…