Java设计模式之行为型模式

行为型模式概述

行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它设计算法与对象间职责的分配。

行为型模式分为类行为模式对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合对象间分配行为。由于组合关系或聚合关系比继承关系耦合低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。

注意:除了模板方法模式和解释器模式是类行为模式,其余的全部属于对象行为模式

模板方法模式(Template Method Patten)

  • 定义:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤。

  • 模板方法(Template Method)模式包含以下主要角色:

    • 抽象类(Abstract Class):负责给出一个算法的框架。它由一个模板方法和若干个基本方法构成。

      • 模板方法:定义了算法的框架,按某种顺序调用其包含的基本方法。

      • 基本方法:是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为三种:

        • 抽象方法(Abstract Method):一个抽象方法由抽象类声明,由其具体子类实现。

        • 具体方法(Concrete Method):一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。

        • 钩子方法(Hook Method):在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。一般钩子方法是用于判断的逻辑方法,这类方法名一般为isXXX,返回值类型为boolean类型。

    • 具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的组成步骤。

  • 案例(炒菜)

    • 抽象类AbstractClass:定义模板方法和基本方法

    public abstract class AbstractClass{
        
        //模板方法定义
        public final 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("翻炒");
        }
    }
    • ConcreteClass_BaoCai

    public class ConcreteClass_BaoCai extends AbstractClass{
        
        public void pourVegetable(){
            System.out.println("下锅的蔬菜是包菜");
        }
        
        public void pourSauce(){
            System.out.println("下锅的酱料是辣椒");
        }
    }
    • ConcreteClass_CaiXin

    public class ConcreteClass_CaiXin extends AbstractClass{
        
        public void pourVegetable(){
            System.out.println("下锅的蔬菜是菜心");
        }
        
        public void pourSauce(){
            System.out.println("下锅的酱料是蒜蓉");
        }
    }
    • 客户端类(Client)

    public class Client{
        public static void main(String[] args){
            //炒包菜
            //创建对象
            ConcreteClass_BaoCai baocai = new ConcreteClass_BaoCai();
            //调用炒菜的功能
            baocai.cookProcess();
        }
    }

策略模式(Strategy Patten)

  • 定义:定义一系列算法,将每一个算法封装起来,使它们可以相互替换。策略模式让算法可以独立于使用它的客户变化。

  • 策略模式的主要角色如下:

    • 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需接口。

    • 具体策略类(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。

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

  • 案例(促销活动)

    • 定义百货公司所有促销活动的共同接口

    public interface Strategy{
        void show();
    }
    • 定义具体策略角色(Concrete Strategy):每个节日具体的促销活动

    //为春节准备的促销活动A
    public class StrategyA implements Strategy{
        
        public void show(){
            System.out.println("买一送一");
        }
    }
    ​
    //为中秋准备的促销活动B
    public class StrategyB implements Strategy{
        
        public void show(){
            System.out.println("满200元减50元");
        }
    }
    ​
    //为圣诞节准备的促销活动C
    public class StrategyC implements Strategy{
        
        public void show(){
            System.out.println("所有商品打五折");
        }
    }
    • 定义环境角色(Context):用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员

    public class SalesMan{
        //持有抽象策略角色的引用
        private Strategy strategy;
        
        public SalesMan(Strategy strategy){
            this.strategy = strategy;
        }
        
        //setter和getter方法
        
        //向客户展示促销活动
        public void salesManShow(){
            strategy.show();
        }
    }
    • 客户端(Client)

    public class Client{
        public static void main(String[] args){
            //春节来了,使用春节促销活动
            SalesMan s = new SalesMan(new StrategyA());
            s.salesManShow();
            
            System.out.println("==========");
            
            //中秋节来了,使用中秋节促销活动
            s.setStrategy(new StrategyB())
            s.salesManShow();
            
            System.out.println("==========");
            
            //圣诞节来了,使用圣诞节促销活动
            s.setStrategy(new StrategyC())
            s.salesManShow();
        }
    }

命令模式(Command Pattern)

  • 定义:将一个请求封装为一个对象,从而让你可以用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作。

  • 命令模式包含以下主要角色:

    • 抽象命令类(Command)角色:定义命令的接口,声明执行的方法

    • 具体命令(Concrete Command)角色:具体的命令,实现命令的接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。

    • 实现者/接收者(Receiver)角色:接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。

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

  • 案例(点餐)

    • 订单类

    public class Order{
        //餐桌号码
        private int diningTable;
        
        //所下的餐品及份数
        private Map<String,Integer> foodDir = new HashMap<String,Integer>();
        
        //setter和getter方法
        
        public void setFood(String name,int num){
            foodDir.put(name,num);
        }
        
    }
    
    • 接收者厨师类

    public class SeniorChef{
        
        public void makeFood(String name,int num){
            System.out.println(num + "份" + name);
        }
    }
    • 抽象命令接口

    public interface Command{
        void execute();
    }
    • 具体命令类

    public class OrderCommand implements Command{
        //持有接收者对象
        private SeniorChef receiver;
        private Order order;
        
        public OrderCommand(SeniorChef receiver, Order order){
            this.reciver = receiver;
            this.order = order;
        }
        
        public void execute(){
            System.out.println(order.getDiningTable() + "桌的订单:");
            Map<String,Integer> foodDir = order.getFoodDir();
            //遍历Map集合
            Set<String> keys = foodDir.keySet();
            for(String foodName : keys){
                receiver.makeFood(foodName,foodDir.get(foodName));
            }
            
            System.out.println(order.getDiningTable() + "桌的饭准备完毕~");
        }
    }
    • 服务员类

    public class Waiter{
        //持有多个命令对象
        private List<Command> commands = new ArrayList<Command>();
        
        public void setCommand(Command cmd){
            //将cmd对象存储到list集合中
            commands.add(cmd);
        }
        
        
        //发起命令的功能
        public void orderUp(){
            System.out.println("新订单来了!");
            //遍历list集合
            for(Command command : commands){
                if(command != null){
                    command.execute();
                }
            }
        }
    }
    • 客户端(Client)

    public class Client{
        public static void main(String[] args){
            //创建第一个订单对象
            Order order1 = new Order();
            order1.setDiningTable(1);
            order1.setFood("西红柿鸡蛋面",1);
            order1.setFood("小杯可乐",2);
            
            //创建第二个订单对象
            Order order2 = new Order();
            order2.setDiningTable(2);
            order2.setFood("尖椒肉丝盖饭",1);
            order2.setFood("小杯雪碧",2);
            
            //创建厨师对象
            SeniorChef receiver = new SeniorChef();
            //创建命令对象
            OrderCommand cmd1 = new OrderCommand(receiver,order1);
            
            OrderCommand cmd2 = new OrderCommand(receiver,order2);
            
            //创建调用者(服务员对象)
            Waiter invoker = new Waiter();
            invoker.setCommand(cmd1);
            invoker.setCommand(cmd2);
            
            //让服务员发起命令
            invoker.orderUp();
        }
    }

职责链模式(Chain of Responsibility Patten)

  • 定义:避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求,直到有一个对象能够处理它为止。

  • 职责链模式主要包含以下角色:

    • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。

    • 具体处理者(Concrete Handler)角色:实现抽象处理中的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。

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

  • 案例(请假流程)

    • 请假条类

    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;
        }
        
        //getter方法
    }
    • 抽象处理者类

    public abstract class Handler{
        protected final static int NUM_ONE = 1;
        protected final static int NUM_THREE = 3;
        protected final static 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 handler){
            this.nextHandler = nextHandler;
        }
        
        //各级领导处理请假条的方法
        protected abstract void handleLeave(LeaveRequest leave);
        
        //提交请假条
        public final void submit(LeaveRequest leave){
            //领导进行审批
            this.handleLeave(leave);
            if(this.nextHandler != null && leave.getNum() > this.numEnd()){
                //提交给上级领导进行审批
                this.nextHandler.submit(leave);
            }else{
                System.out.println("流程结束!");
            }
        }
    }
    • 小组长类

    public class GroupLeader extends Handler{
        public GroupLeader(){
            super(0,Handler.NUM_ONE);
        }
        
        protected void handleLeave(LeaveRequest leave){
            System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
            System.out.println("小组长审批:同意!");
        }
    }
    • 部门经理类

    public class Manager extends Handler{
        public Manager(){
            super(Handler.NUM_ONE,Handler.NUM_THREE);
        }
        
        protected void handleLeave(LeaveRequest leave){
            System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
            System.out.println("部门经理审批:同意!");
        }
    }
    • 总经理类

    public class GeneralManager extends Handler{
        public GeneralManager(){
            super(Handler.NUM_THREE,Handler.NUM_SEVEN);
        }
        
        protected void handleLeave(LeaveRequest leave){
            System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
            System.out.println("总经理审批:同意!");
        }
    }
    • 客户端(Client)

    public class Client{
        public static void main(String[] args){
            //创建一个请假条对象
            LeaveRequest leave = new LeaveRequest("小明",1,"身体不适");
            
            //创建各级领导对象
            GroupLeader gl = new GroupLeader();
            Manager m = new Manager();
            GeneralManager gm = new GeneralManager();
            
            //设置处理者链
            gl.setNextHandler(m);
            m.setNextHandler(gm);
            
            //小明提交请假申请
            gl.submit(leave);
        }
    }

状态模式(State Patten)

  • 定义:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

  • 状态模式包含以下主要角色:

    • 环境(Context)角色:也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。

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

    • 具体状态(Concrete State)角色:实现抽象状态所对应的行为。

  • 案例(电梯)

    • 抽象状态类

    public abstract class LiftState{
        
        //声明一个环境角色变量
        protected Context context;
        
        public void set Context(Context context){
            this.context = context;
        }
        
      	
        //电梯操作功能
        public abstract void open();
        
        public abstract void close();
        
        public abstract void run();
        
        public abstract void stop();
    }
    • 电梯开启状态类

    public class OpeningState extends LiftState{
        public void open(){
            System.out.println("电梯开启...");
        }
        
        public void close(){
           	//修改状态
           	super.context.setLiftState(Context.CLOSING_STATE;
           	//调用当前状态中的context中的close方法
           	super.context.close();
        }
        
        public void run(){
            //什么都不做
        }
        
        public void stop(){
            //什么都不做
        }
    }
    • 电梯关闭状态类

    public class ClosingState extends LiftState{
        public void open(){
            super.context.setLiftState(Context.OPENING_STATE);
            super.context.open();
        }
        
        public void close(){
            System.out.println("电梯门关闭");
        }
        
        public void run(){
            super.context.setLiftState(Context.RUNNING_STATE);
            super.context.run();
        }
        
        public void stop(){
            super.context.setLiftState(Context.STOPPING_STATE);
            super.context.stop();
        }
    }
    • 电梯运行状态类

    public class RunningState extends LiftState{
        public void open(){
            //什么都不做
        }
        
        public void close(){
            //什么都不做
        }
        
        public void run(){
            System.out.println("电梯正在运行...");
        }
        
        public void stop(){
            super.context.setLiftState(Context.STOPPING_STATE);
            super.context.stop();
        }
    }
    • 电梯停止状态类

    public class StoppingState extends LiftState{
        public void open(){
            //状态修改
            super.context.setLiftState(Context.OPENING_STATE);
            //动作委托为closeState来执行,也就是委托给了closingState子类执行这个动作
            super.context.getLiftState().open();
        }
        
        public void close(){
            //状态修改
            super.context.setLiftState(Context.CLOSING_STATE);
            //动作委托为closeState来执行,也就是委托给了closingState子类执行这个动作
            super.context.getLiftState().close();
        }
        
        public void run(){
            //状态修改
            super.context.setLiftState(Context.RUNNING_STATE);
            //动作委托为closeState来执行,也就是委托给了closingState子类执行这个动作
            super.context.getLiftState().run();
        }
        
        public void stop(){
            System.out.println("电梯停止了......");
        }
    }
    • 环境类(Context)

    public class Context{
        
        //定义对应状态对象的常量
        public final static OpeningState OPENING_STATE = new OpeningState();
        public final static ClosingState CLOSING_STATE = new ClosingState();
        public final static RunningState RUNNING_STATE = new RunningState();
        public final static StoppingState STOPPING_STATE = new StoppingState();
        
        //定义一个当前电梯状态变量
        private LiftState liftState;
        
        public LiftState getLiftState(){
            return liftState;
        }
        
        //设置当前状态对象
        public void setLiftState(LiftState liftState){
            this.liftState = liftState;
            
            //设置当前状态对象中的Context对象
            this.liftState.setContext();
        }
        
    	public void open(){
            this.liftState.open();
        }
        
        public void close(){
            this.liftState.close();
        }
        
        public void run(){
            this.liftState.run();
        }
        
        public void stop(){
            this.liftState.stop();
        }
        
    }
    • 客户端类(Client)

    public class Client{
        public static void main(String[] args){
            //创建环境角色对象
            Context context = new Context();
            context.setLiftState(new RunningState());
            
            context.open();
            context.close();
            context.run();
            context.stop();
        }
    }

观察者模式(Observer State)

  • 定义:定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被自动更新。

  • 观察者模式中有如下角色:

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

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

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

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

  • 案例(微信公众号)

    • 抽象主题类

    public interface Subject {
        //添加订阅者(添加观察者对象)
        void attach(Observer observer);
    
        //删除订阅者
        void detach(Observer observer);
    
        //通知订阅者更新消息
        void notify(String message);
    }
    • 具体主题类

    public class SubscriptionSubject implements Subject{
    
        //定义一个集合,用来存储多个观察者对象
        private List<Observer> weixinsUserList = new ArrayList<Observer>();
    
        @Override
        public void attach(Observer observer) {
            weixinsUserList.add(observer);
        }
    
        @Override
        public void detach(Observer observer) {
            weixinsUserList.remove(observer);
        }
    
        @Override
        public void notify(String message) {
            //遍历集合
            for(Observer observer : weixinsUserList){
                //调用观察者对象中的update方法
                observer.update(message);
            }
        }
    }
    • 抽象观察者类

    public interface Observer {
        void update(String message);
    }
    • 具体观察者类

    public class WeiXinUser implements Observer{
    
    
        private String name;
    
        public WeiXinUser(String name) {
            this.name = name;
        }
    
        @Override
        public void update(String message) {
            System.out.println(name + "-" + message);
        }
    }
    • 客户端类

    public class Client {
        public static void main(String[] args) {
            //1.创建公众号
            SubscriptionSubject subject = new SubscriptionSubject();
    
            //2.订阅公众号
            subject.attach(new WeiXinUser("孙悟空"));
            subject.attach(new WeiXinUser("猪悟能"));
            subject.attach(new WeiXinUser("沙悟净"));
    
            //3.公众号更新,发出消息给订阅者(观察者对象)
            subject.notify("更新了!~~");
        }
    }

中介者模式(Mediator Patten)

  • 定义:定义一个对象来封装一系列对象的交互。中介者模式使各对象之间不需要显式地相互引用,从而使其耦合松散,而且让你可以独立地改变它们之间的交互。

  • 中介者模式包含以下主要角色:

    • 抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。

    • 具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个List来管理同事对象,协调各个同事角色之间的交互关系,因此它们依赖于同事角色。

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

    • 具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

  • 案例(房屋中介)

    • 抽象中介者类

    public abstract class Mediator {
        public abstract void contract(String message,Person person);
    }
    • 具体中介者类

    public class MediatorStructure extends Mediator{
    
        //聚合房主和租房者对象
        private HouseOwner houseOwner;
        private Tenant tenant;
    
        public HouseOwner getHouseOwner() {
            return houseOwner;
        }
    
        public void setHouseOwner(HouseOwner houseOwner) {
            this.houseOwner = houseOwner;
        }
    
        public Tenant getTenant() {
            return tenant;
        }
    
        public void setTenant(Tenant tenant) {
            this.tenant = tenant;
        }
    
        @Override
        public void contract(String message, Person person) {
            if(person == houseOwner){
                tenant.getMessage(message);
            }else {
                houseOwner.getMessage(message);
            }
        }
    }
    • 抽象同事类

    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 contract(String message){
            mediator.contract(message,this);
        }
    
        //获取信息
        public void  getMessage(String message){
            System.out.println("租房者" + name + "获取到的信息是:" + message);
        }
    }
    • 房主类

    public class HouseOwner extends Person{
        public HouseOwner(String name, Mediator mediator) {
            super(name, mediator);
        }
    
        //和中介联系(沟通)
        public void contract(String message){
            mediator.contract(message,this);
        }
    
        //获取信息
        public void  getMessage(String message){
            System.out.println("房主" + name + "获取到的信息是:" + message);
        }
    }
    • 客户端类

    public class Client {
        public static void main(String[] args) {
            //创建中介者对象
            MediatorStructure mediatorStructure = new MediatorStructure();
    
            //创建租房者对象
            Tenant tenant = new Tenant("李四",mediatorStructure);
    
            //创建房主对象
            HouseOwner houseOwner = new HouseOwner("张三",mediatorStructure);
    
            //中介者要知道具体的房主和租房者
            mediatorStructure.setTenant(tenant);
            mediatorStructure.setHouseOwner(houseOwner);
    
            tenant.contract("我要租三室一厅的房子");
            houseOwner.contract("我这里有三室一厅的房子,你要租吗?");
        }
    }

迭代器模式(Iterator Pattern)

  • 定义:提供一种方法顺序访问一个聚合对象中各个元素,而不用暴露该对象的内部表示。

  • 迭代器模式主要包含以下角色:

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

    • 具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。

    • 抽象迭代器(Iterator)角色:定义访问和遍历元素的接口,通常包含hashNext()、next()等方法。

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

  • 案例(存储学生对象)

    • 抽象聚合类

    public interface StudentAggregate {
    
        //添加学生功能
        void addStudent(Student stu);
    
        //删除学生功能
        void removeStudent(Student stu);
    
        //获取迭代器对象
        StudentIterator getStudentIterator();
    }
    
    • 具体聚合类

    public class StudentAggregateImpl implements StudentAggregate{
    
        private List<Student> list = new ArrayList<Student>();
    
        @Override
        public void addStudent(Student stu) {
            list.add(stu);
        }
    
        @Override
        public void removeStudent(Student stu) {
            list.remove(stu);
        }
    
        @Override
        public StudentIterator getStudentIterator() {
            return new StudentIteratorImpl(list);
        }
    }
    • 抽象迭代器类

    public interface StudentIterator {
    
        //判断是否还有元素
        boolean hashNext();
    
        //获取下一个元素
        Student next();
    }
    

    • 具体迭代器类

    public class StudentIteratorImpl implements StudentIterator{
    
        private List<Student> list;
        private int position = 0;//用来记录遍历时的位置
    
        public StudentIteratorImpl(List<Student> list) {
            this.list = list;
        }
    
        @Override
        public boolean hashNext() {
            return position < list.size();
        }
    
        @Override
        public Student next() {
            //从集合中获取指定位置的元素
            Student student = list.get(position);
            position++;
            return student;
        }
    }
    • Student类

    public class Student {
        private String name;
        private String number;
    
        public Student(String name, String number) {
            this.name = name;
            this.number = number;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getNumber() {
            return number;
        }
    
        public void setNumber(String number) {
            this.number = number;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", number='" + number + '\'' +
                    '}';
        }
    }
    • 客户端类

    public class Client {
        public static void main(String[] args) {
            //创建聚合对象
            StudentAggregateImpl aggregate = new StudentAggregateImpl();
            //添加元素
            aggregate.addStudent(new Student("张三","001"));
            aggregate.addStudent(new Student("李四","002"));
            aggregate.addStudent(new Student("王五","003"));
            aggregate.addStudent(new Student("赵六","004"));
    
            //遍历聚合对象
            //1.获取迭代器对象
            StudentIterator iterator = aggregate.getStudentIterator();
    
            //2.遍历
            while (iterator.hashNext()){
                //3.获取元素
                Student student = iterator.next();
                System.out.println(student.toString());
            }
        }
    }

访问者模式(Visitor Pattern)

  • 定义:表示一个作用于某对象结构中的各个元素的操作。访问者模式让你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

  • 访问者模式包含以下主要角色:

    • 抽象访问者(Visitor)角色:定义了对每一个元素(Element)访问的行为,它的参数就是可以访问的元素,它的方法个数理论上来讲与元素类个数(Element的实现类个数)是一样的,从这点不难看出,访问者模式要求元素类的个数不能改变。

    • 具体访问者(ConcreteVisitor)角色:给出每一个元素类访问时所产生的具体行为

    • 抽象元素(Element)角色:定义了一个接收访问者的方法(accept),其意义是指,每一个元素都要可以被访问者访问。

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

    • 对象结构(Object Structure)角色:定义当中所提到的对象结构,对象结构是一个抽象表述,具体可以理解为一个具有容器性质或者符合对象特性的类,它会含有一组元素(Element),并且可以迭代这些元素,供访问者访问。

  • 案例(给宠物喂食)

    • 抽象访问者Person类

    public interface Person {
        void feed(Cat act);
    
        void feed(Dog dog);
    }
    • 具体访问者Owner类

    public class Owner implements Person{
        @Override
        public void feed(Cat act) {
            System.out.println("主人喂食猫");
        }
    
        @Override
        public void feed(Dog dog) {
            System.out.println("主人喂食狗");
        }
    }
    • 具体访问者Other_Person类

    public class Other_Person implements Person{
        @Override
        public void feed(Cat act) {
            System.out.println("其他人喂食猫");
        }
    
        @Override
        public void feed(Dog dog) {
            System.out.println("其他人喂食狗");
        }
    }
    • 抽象元素Animal类

    public interface Animal {
    
        //提供接收访问者访问的功能
        void accept(Person person);
    }
    • 具体元素Dog类

    public class Dog implements Animal{
        @Override
        public void accept(Person person) {
            person.feed(this);//访问者给宠物狗喂食
            System.out.println("好好吃,汪汪~");
        }
    }
    • 具体元素Cat类

    public class Cat implements Animal{
        @Override
        public void accept(Person person) {
            person.feed(this);//访问者给宠物猫喂食
            System.out.println("好好吃,喵喵~~");
        }
    }
    • 结构对象类

    public class Home {
        //声明一个集合对象,用来存储元素对象
        private List<Animal> nodeList = new ArrayList<Animal>();
    
        //添加元素功能
        public void add(Animal animal){
            nodeList.add(animal);
        }
    
        public void action(Person person){
            //遍历元素,获取每一个元素,让访问者访问每一个元素
            for (Animal animal : nodeList){
                animal.accept(person);
            }
        }
    }
    • 客户端类

    public class Client {
        public static void main(String[] args) {
            //创建Home对象
            Home home = new Home();
            //添加元素到Home中
            home.add(new Dog());
            home.add(new Cat());
    
            //创建主人对象
            Owner owner = new Owner();
            
            //让主人喂食所有宠物
            home.action(owner);
        }
    }

备忘录模式(Memento Pattern)

  • 定义:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样就可以在以后将对象恢复到原先保存的状态

  • 备忘录模式的主要角色如下:

    • 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息

    • 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人

    • 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问。

  • 备忘录有两个等效接口:

    • 窄接口:管理者(Caretaker)对象(和其他发起人对象之外的任何对象)看到的是备忘录的窄接口(narrow Interface),这个窄接口只允许他把备忘录对象传给其他的对象。

    • 宽接口:与管理者看到的窄接口相反,发起人对象可以看到一个宽接口(wide Interface),这个宽接口允许它读取所有的数据,一遍根据这些数据恢复这个人发起对象的内部状态。

  • 案例(游戏挑战BOSS)

    • 白箱备忘录模式

    • 发起人GameRole类

    public class GameRole {
    
        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 RoleStateMemento saveState(){
            return new RoleStateMemento(vit,atk,def);
        }
    
        //恢复角色状态
        public void recoverState(RoleStateMemento 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);
        }
    	//getter和setter方法
    }
    • 备忘录RoleStateMemento类

    public class RoleStateMemento {
    
        private int vit;    //生命力
        private int atk;    //攻击力
        private int def;    //防御力
    
        public RoleStateMemento(int vit, int atk, int def) {
            this.vit = vit;
            this.atk = atk;
            this.def = def;
        }
    
        public RoleStateMemento() {
        }
    
        //getter和setter方法
    }
    • 备忘录管理者RoleStateCaretaker类

    public class RoleStateCaretaker {
    
        //声明roleStateCaretaker类型的变量
        private RoleStateMemento roleStateMemento;
    
        public RoleStateMemento getRoleStateMemento() {
            return roleStateMemento;
        }
    
        public void setRoleStateMemento(RoleStateMemento roleStateMemento) {
            this.roleStateMemento = roleStateMemento;
        }
    }
    • 客户端类

    public class Client {
        public static void main(String[] args) {
            System.out.println("---------大战BOSS前--------");
    
            //创建游戏角色对象
            GameRole gameRole = new GameRole();
            gameRole.initState();//初始化状态操作
            gameRole.stateDisplay();
    
            //将该游戏角色内部状态进行备份
            //创建管理者对象
            RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
            roleStateCaretaker.setRoleStateMemento(gameRole.saveState());
    
            System.out.println("---------大战BOSS后--------");
    
            //损耗严重
            gameRole.fight();
            gameRole.stateDisplay();
    
            System.out.println("---------恢复之前的状态--------");
            gameRole.recoverState(roleStateCaretaker.getRoleStateMemento());
            gameRole.stateDisplay();
        }
    }
    • 黑箱备忘录模式

    • 发起人GameRole类

    public class GameRole {
    
        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 Memento saveState(){
            return new RoleStateMemento(vit,atk,def);
        }
    
        //恢复角色状态
        public void recoverState(Memento memento){
            RoleStateMemento roleStateMemento = (RoleStateMemento) memento;
            //将备忘录对象中存储的对象状态赋值给当前对象的成员
            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);
        }
    
        //getter和setter方法
        
        private class RoleStateMemento implements Memento{
            private int vit;    //生命力
            private int atk;    //攻击力
            private int def;    //防御力
    
            public RoleStateMemento() {
            }
    
            public RoleStateMemento(int vit, int atk, int def) {
                this.vit = vit;
                this.atk = atk;
                this.def = def;
            }
    		//getter和setter方法
        }
    }
    • Memento接口

    public interface Memento {
    }
    • 备忘录管理者类

    public class RoleStateCaretaker {
    
        //声明roleStateCaretaker类型的变量
        private Memento memento;
    
        public Memento getMemento() {
            return memento;
        }
    
        public void setMemento(Memento memento) {
            this.memento = memento;
        }
    }
    • 客户端类

    public class Client {
        public static void main(String[] args) {
            System.out.println("---------大战BOSS前--------");
    
            //创建游戏角色对象
            GameRole gameRole = new GameRole();
            gameRole.initState();//初始化状态操作
            gameRole.stateDisplay();
    
            //将该游戏角色内部状态进行备份
            //创建管理者对象
            RoleStateCaretaker roleStateCaretaker = new RoleStateCaretaker();
            roleStateCaretaker.setMemento(gameRole.saveState());
    
            System.out.println("---------大战BOSS后--------");
    
            //损耗严重
            gameRole.fight();
            gameRole.stateDisplay();
    
            System.out.println("---------恢复之前的状态--------");
            gameRole.recoverState(roleStateCaretaker.getMemento());
            gameRole.stateDisplay();
        }
    }

解释器模式(Interpreter Patten)

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

  • 解释器模式包含以下主要角色:

    • 抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的操作,主要包含解释方法interpret()。

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

    • 非终结符表达式(Nonterminanl Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。

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

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

  • 案例(实现加减法的软件)

    • 抽象表达式AbstractExpression类

    public abstract class AbstractExpression {
        public abstract int interpret(Context  context);
    }
    • 终结符表达式Variable类

    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;
        }
    }
    • 非终结符表达式Plus类

    public class Plus extends AbstractExpression{
    
        //+号左边的表达式
        private AbstractExpression left;
    
        //+号右边的表达式
        private AbstractExpression right;
    
        public Plus(AbstractExpression left, AbstractExpression right) {
            this.left = left;
            this.right = right;
        }
    
        @Override
        public int interpret(Context context) {
            //将左边表达式的结果和右边表达式的结果进行相加
    
            return left.interpret(context) + right.interpret(context);
        }
    
        @Override
        public String toString() {
            return "(" + left.toString() + " + "  + right.toString() +")";
        }
    }
    • 非终结符表达式Minus类

    public class Minus extends AbstractExpression{
    
        //-号左边的表达式
        private AbstractExpression left;
    
        //-号右边的表达式
        private AbstractExpression right;
    
        public Minus(AbstractExpression left, AbstractExpression right) {
            this.left = left;
            this.right = right;
        }
    
        @Override
        public int interpret(Context context) {
            //将左边表达式的结果和右边表达式的结果进行相减
    
            return left.interpret(context) - right.interpret(context);
        }
    
        @Override
        public String toString() {
            return "(" + left.toString() + " - "  + right.toString() +")";
        }
    }
    • 环境(Context)类

    public class Context {
    
        //定义一个map集合,用来存储变量对应的值
        private Map<Variable,Integer> map = new HashMap<Variable,Integer>();
    
        //添加变量的功能
        public void assign(Variable var,Integer value){
            map.put(var,value);
        }
    
        //根据变量获取对应的值
        public int getValue(Variable var){
            return map.get(var);
        }
    }
    • 客户端类

    public class Client {
        public static void main(String[] args) {
            //创建环境对象
            Context context = new Context();
    
            //创建多个变量对象
            Variable a = new Variable("a");
            Variable b= new Variable("b");
            Variable c = new Variable("c");
            Variable d = new Variable("d");
    
            //将变量存储到环境对象中
            context.assign(a,1);
            context.assign(b,2);
            context.assign(c,3);
            context.assign(d,4);
    
            //获取抽象语法树   a + b - c + d
            AbstractExpression expression = new Minus(a,new Plus(new Minus(b,c),d));
    
            //解释(计算)
            int result = expression.interpret(context);
    
            System.out.println(expression + " = " + result);
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鱼粮爱编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值