【91-136】行为型模式

news2024/11/17 9:53:21

目录

一.模板方法模式

1.1 概述

1.2 结构

1.3 案例

1.4 优缺点

1.5 使用场景

二.策略模式

2.1 概述

2.2  结构

2.3 案例

2.4 优缺点

2.5 使用场景

2.6 JDK 源码解析

三.命令模式

3.1 概述

3.2 结构

3.3 案例

3.4 优缺点

3.5 使用场景

四.责任链模式

4.1 概述

4.2 结构

4.3 案例

4.4 优缺点

五.状态模式

5.1 概述

5.2 结构

5.3 案例

5.4 优缺点

5.5 使用场景

六.观察者模式

6.1 概述

6.2 结构

6.3 案例

6.4 优缺点

6.5 使用场景

七.中介者模式

7.1 概述

7.2 结构

7.3 案例

7.4 优缺点

7.5 使用场景

八.迭代器模式

8.1 概述

8.2 结构

8.3 案例

8.4 优缺点

8.5 使用场景

九.访问者模式

9.1 概述

9.2 结构

9.3 案例

9.4 优缺点 

9.5 使用场景

十.备忘录模式

10.1 概述

10.2 结构

10.3 案例

10.3.1 “白箱”备忘录模式

10.3.2 “黑箱”备忘录模式

10.4 优缺点

10.5 使用场景

十一.解释器模式

11.1 概述

11.2 结构

11.3 案例

11.4 优缺点

11.5 使用场景


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

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

行为型模式分为:

  • 模板方法模式
  • 策略模式
  • 命令模式
  • 职责链模式
  • 状态模式
  • 观察者模式
  • 中介者模式
  • 迭代器模式
  • 访问者模式
  • 备忘录模式
  • 解释器模式

以上11中行为型模式,除了模板方法模式和解释器模式时类行为型模式,其他都是对象行为型模式。

一.模板方法模式

1.1 概述

定义:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中【但是要在父类中进行抽象声明】,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。

1.2 结构

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

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

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

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

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

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

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

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

1.3 案例

【例】炒菜

AbstractClass抽象类

//抽象类(定义模板方法和基本方法)
public abstract class AbstractClass {

    //模板方法定义(不想被改变,加final)
    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();

        System.out.println("========================");
        //炒菜心
        ConcreteClass_CaiXin caiXin=new ConcreteClass_CaiXin();
        caiXin.cookProcess();
    }

1.4 优缺点

1.5 使用场景

二.策略模式

2.1 概述

定义:

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

2.2  结构

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

  • 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或者抽象类实现。此角色给出所有具体策略类所需的接口。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体算法实现或行为。
  • 环境(Context)类:持有一个策略类的引用,最终给客户端调用。

2.3 案例

【例】促销活动

Strategy抽象策略类

//抽象策略类
public interface Strategy {

    void show();
}

StrategyA具体策略类

//具体策略类
public class StrategyA implements Strategy {
    public void show(){
        System.out.println("买一送一");
    }
}

StrategyB具体策略类

//具体策略类
public class StrategyB implements Strategy {
    public void show(){
        System.out.println("满200减50");
    }
}

StrategyC具体策略类

//具体策略类
public class StrategyC implements Strategy {
    public void show(){
        System.out.println("满1000减500");
    }
}

SaleMan环境类

//促销员(环境类)
public class SaleMan {

    //聚合策略类对象
    private Strategy strategy;

    public SaleMan(Strategy strategy) {
        this.strategy = strategy;
    }

    //由促销员展示促销活动给普通用户
    public void saleManShow(){
        strategy.show();
    }
}

Client测试类

public class Client {
    public static void main(String[] args) {
        //春节来了,使用春节促销活动StrategyA
        SaleMan saleMan=new SaleMan(new StrategyA());
        saleMan.saleManShow();

        System.out.println("==================");
        //中秋节,使用中秋节的促销活动StrategyB
        SaleMan saleMan2=new SaleMan(new StrategyB());
        saleMan2.saleManShow();

        System.out.println("==================");
        //圣诞节,使用圣诞节的促销活动StrategyB
        SaleMan saleMan3=new SaleMan(new StrategyC());
        saleMan3.saleManShow();
    }

}

2.4 优缺点

2.5 使用场景

2.6 JDK 源码解析

三.命令模式

3.1 概述

定义:

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

3.2 结构

3.3 案例

服务员:调用者角色,由她来发起命令

资深大厨:接收者角色,真正命令执行的对象

订单:命令中包含订单

Order订单类

//订单类
public class Order {
    //餐桌号码
    private int diningtable;
    //所下的餐品及份数
    private Map<String, Integer> foodDir=new HashMap<String, Integer>();;

    public void setDiningtable(int diningtable) {
        this.diningtable = (int) diningtable;
    }

    public int getDiningtable() {
        return diningtable;
    }

    public Map<String, Integer> getFoodDir() {
        return foodDir;
    }

    public void setFood(String name, int num) {
        foodDir.put(name, num);
    }

}

Command抽象命令类

//抽象命令类
public interface Command {

    void execute();

}

OrderCommand具体命令类

//具体命令类
public class OrderCommand implements Command{

    //持有接收者对象
    private SeniorChef reciver;
    private Order order;

    public OrderCommand(SeniorChef reciver, Order order) {
        this.reciver = reciver;
        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){
            reciver.makeFood(foodName, foodDir.get(foodName));
        }
        System.out.println(order.getDiningtable()+"桌的饭准备完毕!!!");
    }

}

SeniorChef接收者类

//厨师类
public class SeniorChef {

    public void makeFood(String name, int num){
        System.out.println(num+"份"+name);
    }
}

Waitor调用者类

// 服务员类(属于请求者角色)
public class Waitor {

    //持有多个命令对象
    private List<Command> commands=new ArrayList<Command>();

    public void setCommands(Command cmd){
        //将cmd对象存储倒list对象中
        commands.add(cmd);
    }

    //发起命令功能 喊 订单来了
    public void orderUp(){
        System.out.println("Order up。。。。");
        //遍历list集合
        for(Command cmd:commands){
            if(cmd!=null){
                cmd.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("小杯雪碧",1);

        //创建厨师对象
        SeniorChef receiver = new SeniorChef();
        //创建命令对象
        OrderCommand cmd1=new OrderCommand(receiver,order1);
        OrderCommand cmd2=new OrderCommand(receiver,order2);

        //创建调用者(服务员对象)
        Waitor invoke =new Waitor();
        invoke.setCommands(cmd1);
        invoke.setCommands(cmd2);

        //让服务员发起命令
        invoke.orderUp();
    }
}

3.4 优缺点

3.5 使用场景

四.责任链模式

4.1 概述

定义:

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

4.2 结构

4.3 案例

现在需要开发1一个请假流程控制系统,请假一天以下只需要找小组长同意即可;请假1天到3天需要部门经理同意;请假3天到7天还需要总经理同意才行。

Handler抽象处理者角色

//抽象处理者
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) {
        this.numStart = numStart;
    }

    public Handler(int numStart, int numEnd) {
        this.numEnd = numEnd;
        this.numStart = numStart;
    }

    //设置上级领导对象
    public void setNextHandler(Handler nextHandler) {
        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);
        }
    }
}

GroupLeader具体处理者角色

//小组长类(具体处理者)
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("小组长审批:同意");
    }

}

Manager具体处理者角色

//部门经理类(具体处理者)
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("部门经理审批:同意");
    }

}

GeneralManager具体处理者角色

//总经理类(具体处理者)
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("总经理审批:同意");
    }

}

LeaveRequest请假条类

//请假条类
public class LeaveRequest {

    //姓名
    private String name;

    //请假天数
    public int num;

    //请假内容
    private String content;

    public LeaveRequest(String name, int num, String content) {
        this.name = name;
        this.num = num;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public int getNum() {
        return num;
    }

    public String getContent() {
        return content;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

Client客户类角色

public class Client {
    public static void main(String[] args) {
        //创建一个请假条对象
        LeaveRequest leave=new LeaveRequest("小明",1,"身体不适");

        //创建各级领导对象
        GroupLeader groupLeader=new GroupLeader();
        Manager manager=new Manager();
        GeneralManager generalManager=new GeneralManager();

        //设置处理者链
        groupLeader.setNextHandler(manager);
        manager.setNextHandler(generalManager);

        //小明提交请假申请
        groupLeader.submit(leave);
    }
}

4.4 优缺点

优点:

缺点:

五.状态模式

5.1 概述

【例】通过按钮来控制一个电梯的状态,一个电梯有开门状态、关门状态、停止状态、运行状态。每一种状态改变,都可能要根据其他状态来更新处理。例如如果电梯现在处于运行时状态,就不能进行开门操作,而如果电梯门是停止状态,就可以执行开门操作。

ILift电梯接口

//电梯接口
public interface ILift {

    //定义四个电梯状态的常量
    int OPENING_STATE = 1;
    int CLOSING_STATE = 2;
    int RUNNING_STATE = 3;
    int STOPPING_STATE = 4;

    //设置电梯状态的功能
    void setState(int state);

    //电梯操作
    void open();
    void close();
    void run();
    void stop();

}

Lift电梯

//电梯类(ILift子实现类)
public class Lift implements ILift{

    //声明一个记录当前电梯状态的变量
    private int state;

    @Override
    public void setState(int state) {
        this.state = state;
    }

    public void open(){
        switch(state){
            //什么都不做
            case OPENING_STATE:break;
            case CLOSING_STATE:
                System.out.println("电梯打开了。。。");
                setState(OPENING_STATE);
                break;
            case STOPPING_STATE:
                System.out.println("电梯打开了。。。");
                setState(OPENING_STATE);
                break;
            case RUNNING_STATE:break;
        }
    }
    public void close(){
        switch(state){
            case OPENING_STATE:
                System.out.println("电梯关闭了。。。");
                setState(CLOSING_STATE);
                break;
            case CLOSING_STATE:
                break;
            case STOPPING_STATE:
                break;
            case RUNNING_STATE:
                break;
        }
    }
    public void run(){
        switch(state){
            case OPENING_STATE:
                break;
            case CLOSING_STATE:
                System.out.println("电梯开始运行了。。。");
                setState(RUNNING_STATE);
                break;
            case STOPPING_STATE:
                System.out.println("电梯开始运行了。。。");
                setState(RUNNING_STATE);
                break;
            case RUNNING_STATE:
                break;
        }
    }
    public void stop(){
        switch(state){
            //什么都不做
            case OPENING_STATE:
                break;
            case CLOSING_STATE:
                System.out.println("电梯停止了。。。");
                setState(STOPPING_STATE);
                break;
            case STOPPING_STATE:
                break;
            case RUNNING_STATE:
                System.out.println("电梯停止了。。。");
                setState(STOPPING_STATE);
                break;
        }
    }
}

Client测试类

public class Client {
    public static void main(String[] args) {
        //创建电梯对象
        Lift lift = new Lift();

        //设置当前电梯状态
        lift.setState(ILift.OPENING_STATE);

        //打开
        lift.open();

        lift.close();

        lift.run();

        lift.stop();
    }
}

问题分析:

  • 使用了大量的switch。。。case这样的判断(if。。。else也是一样),使程序可读性变差。
  • 扩展性很差。如果新增断电状态,我们需要修改上面判断逻辑。

定义:

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

5.2 结构

5.3 案例

5.4 优缺点

5.5 使用场景

六.观察者模式

6.1 概述

定义:

又被称为发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态改变时,会通知所有的观察者对象,使它们能够自动更新自己。

6.2 结构

6.3 案例

【例】微信公众号

Subject抽象主题类

//抽象主题角色
public interface Subject {

    //添加观察者对象
    void attach(Observer observer);

    //删除观察者对象
    void detach(Observer observer);

    //通知观察者更新消息
    void notify(String message);
}

SubscriptionSubject具体主题类

//具体主题角色类
public class SubscriptionSubject implements Subject{

    //定义一个集合,用来存储多个观察者对象
    private List<Observer> WeiXinUserList = new ArrayList<Observer>();

    @Override
    public void attach(Observer observer) {
        WeiXinUserList.add(observer);
    }

    @Override
    public void detach(Observer observer) {
            WeiXinUserList.remove(observer);
    }

    @Override
    public void notify(String message) {
        //遍历集合
        for (Observer observer : WeiXinUserList) {
            //调用观察者对象中update方法
            observer.update(message);
        }
    }
}

Observer抽象观察者类

//抽象观察者类
public interface Observer {

    void update(String message);
}

WeiXinUser具体观察者类

//具体观察者角色类
public class WeiXinUser implements Observer {

    private String name;
    public WeiXinUser(String name) {
        this.name = name;
    }
    public void update(String message) {
        System.out.println("WeiXinUser: " + name + " : " + message);
    }

}

Client测试类

public class Client {
    public static void main(String[] args) {
        //创建公众号对象
        SubscriptionSubject subject = new SubscriptionSubject();

        //订阅公众号
        subject.attach(new WeiXinUser("孙悟空"));
        subject.attach(new WeiXinUser("猪八戒"));
        subject.attach(new WeiXinUser("沙悟净"));

        //公众号更新,发出消息
        subject.notify("传智黑马专栏更新。。。");
    }
}

6.4 优缺点

6.5 使用场景

七.中介者模式

7.1 概述

定义:

又叫调停模式,定义一个中介角色来封装一系列对象之间的交互,使原有对象之间耦合松散,且可以独立改变它们之间的交互。

7.2 结构

7.3 案例

【例】租房

现在租房基本都是通过房屋中介,房主将房屋托管给房屋中介,而租房者从房屋中介获取房屋信息。房屋中介充当租房者与房屋所有者之间的中介者。

Mediator抽象中介者角色

//抽象中介者类
public abstract class Mediator {

    public abstract void constact(String message, Person person);
}

MediatorStructure具体中介者角色

//具体中介者角色
public class MediatorStructure extends Mediator {

    //聚合房主和租房者对象
    private HouseOwner houseOwner;
    private Tenant tenant;

    public HouseOwner getHouseOwner() {
        return houseOwner;
    }

    public Tenant getTenant() {
        return tenant;
    }

    public void setHouseOwner(HouseOwner houseOwner) {
        this.houseOwner = houseOwner;
    }

    public void setTenant(Tenant tenant) {
        this.tenant = tenant;
    }

    public void constact(String message, Person person) {
        if(person == houseOwner){
            houseOwner.getMessage(message);
        }
        else{
            tenant.getMessage(message);
        }
    }
}

Person抽象同事角色

public abstract class Person {

    protected String name;
    protected Mediator mediator;

    public Person(String name, Mediator mediator) {
        this.name = name;
        this.mediator = mediator;
    }
}

Tenant具体同事角色(租房者)

//具体同事角色
public class Tenant extends Person{

    public Tenant(String name, Mediator mediator) {
        super(name, mediator);
    }

    //和中介联系(沟通)
    public void constact(String message){
        mediator.constact(message,this);
    }

    //获取信息
    public void getMessage(String message){
        System.out.println("租房者"+name+"获取到的信息是:"+message);
    }
}

HouseOwner具体同事角色(房主)

//具体同事角色类
public class HouseOwner extends Person{

    public HouseOwner(String name, Mediator mediator) {
        super(name, mediator);
    }

    //和中介联系(沟通)
    public void constact(String message){
        mediator.constact(message,this);
    }

    //获取信息
    public void getMessage(String message){
        System.out.println("房主"+name+"获取到的信息是:"+message);
    }
}

Client测试类

public class Client {
    public static void main(String[] args) {
        //创建中介者对象
        MediatorStructure mediator = new MediatorStructure();

        //创建租房者对象
        Tenant tenant=new Tenant("李四",mediator);
        //创建房主对象
        HouseOwner houseOwner=new HouseOwner("张三",mediator);

        //中介者要知道具体的房主和租房者
        mediator.setTenant(tenant);
        mediator.setHouseOwner(houseOwner);

        tenant.constact("我要组三室的房子!!!");
        houseOwner.constact("我这里有三室的房子,你要租吗?");

    }
}

7.4 优缺点

7.5 使用场景

八.迭代器模式

8.1 概述

定义:

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

8.2 结构

8.3 案例

 【例】定义一个可以存储学生对象的容器对象,将遍历容器的功能交由迭代器实现。

StudentIterator抽象迭代器角色

//抽象迭代器角色接口
public interface StudentIterator {

    //判断是否还有元素
    boolean hasNext();

    //获取下一个元素
    Student next();

}

StudentIteratorImpl具体迭代器角色

public class StudentIteratorImpl implements StudentIterator {

    private List<Student> list;
    private int position = 0; //用来记录遍历时的位置

    public StudentIteratorImpl(List<Student> list) {
        this.list = list;
    }

    @Override
    public boolean hasNext() {
        return position < list.size();
    }

    @Override
    public Student next() {
        //从集合中获取指定位置的元素
        Student student = list.get(position);
        position++;
        return student;
    }
}

StudentAggregate抽象聚合角色

//抽象聚合角色接口
public interface StudentAggregate {

    //添加学生功能
    void addStudent(Student student);

    //删除学生功能
    void removeStudent(Student student);

    //获取迭代器对象功能
    StudentIterator getStudentIterator();
}

StudentAggregate具体聚合角色

public class StudentAggregateImpl implements StudentAggregate{

    private List<Student> list=new ArrayList<Student>();

    @Override
    public void addStudent(Student student) {
        list.add(student);
    }

    @Override
    public void removeStudent(Student student) {
        list.remove(student);
    }

    //获取迭代器对象
    @Override
    public StudentIterator getStudentIterator() {
        return new StudentIteratorImpl(list);
    }

}

Student学生类

public class Student {
    private String name;
    private String number;

    public Student() {
    }

    public Student(String name, String number) {
        this.name = name;
        this.number = number;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", number='" + number + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public String getNumber() {
        return number;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setNumber(String number) {
        this.number = number;
    }
}

Client测试类

public class Client {
    public static void main(String[] args) {

        //创建聚合对象
        StudentAggregate 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.hasNext()) {
            System.out.println(iterator.next());
        }

    }
}

8.4 优缺点

8.5 使用场景

九.访问者模式

9.1 概述

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

9.2 结构

9.3 案例

【例】给宠物喂食

现在养宠物的人特别多,我们就以这个为例,当然宠物还分为狗、猫等,要给宠物喂食的话,主人可以喂,其他人也可以喂食。

  • 访问者角色:给宠物喂食的人
  • 具体访问者角色:主人、其他人
  • 抽象元素角色:动物抽象类
  • 具体元素角色:宠物狗、宠物猫
  • 结构对象角色:主人家

9.4 优缺点 

9.5 使用场景

十.备忘录模式

10.1 概述

定义:

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

10.2 结构

10.3 案例

10.3.1 “白箱”备忘录模式

备忘录角色对任何对象都提供一个接口,即宽接口,备忘录角色的内部所存储的状态就对所有对象公开。

 RoleStateMemento备忘录角色

//备忘录角色类
public class RoleStatusMemento {

    private int vit;
    private int atk;
    private int def;

    public RoleStatusMemento(int vit, int atk, int def) {
        this.vit = vit;
        this.atk = atk;
        this.def = def;
    }

    public int getVit() {
        return vit;
    }

    public int getDef() {
        return def;
    }

    public int getAtk() {
        return atk;
    }

    public void setVit(int vit) {
        this.vit = vit;
    }

    public void setDef(int def) {
        this.def = def;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }
}

GameRole发起人角色

//游戏角色类(发起人角色)
public class GameRole {
    private int vit; //生命力
    private int atk; //攻击力
    private int def; //防御力

    //初始化内部状态
    public void iniState(){
        this.vit=100;
        this.atk=100;
        this.def=100;
    }

    //战斗
    public void fight(){
        this.vit=0;
        this.atk=0;
        this.def=0;
    }

    //保存角色状态功能
    public RoleStatusMemento saveState(){
        return new RoleStatusMemento(vit, atk, def);
    }

    //恢复角色状态
    public void recoverState(RoleStatusMemento memento){
        //将备忘录对象中存储的状态赋值给当前对象的成员
        this.vit=memento.getVit();
        this.atk=memento.getAtk();
        this.def=memento.getDef();
    }

    //展示状态功能
    public void stateDisplay(){
        System.out.println("角色生命力:"+getVit());
        System.out.println("角色攻击力:"+getAtk());
        System.out.println("角色防御力:"+getDef());
    }

    public int getAtk() {
        return atk;
    }

    public int getDef() {
        return def;
    }

    public int getVit() {
        return vit;
    }

    public void setVit(int vit) {
        this.vit = vit;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }

    public void setDef(int def) {
        this.def = def;
    }
}

RoleStateCaretaker管理人角色

//备忘录对象管理角色
public class RoleStateCaretaker {

    //声明备忘录类型的变量
    private RoleStatusMemento roleStatusMemento;

    public RoleStatusMemento getRoleStatusMemento() {
        return roleStatusMemento;
    }

    public void setRoleStatusMemento(RoleStatusMemento roleStatusMemento) {
        this.roleStatusMemento = roleStatusMemento;
    }
}

Client测试类

public class Client {
    public static void main(String[] args) {
        System.out.println("--------------------大战boss前----------------");
        //创建游戏角色对象
        GameRole gameRole=new GameRole();
        gameRole.iniState();
        gameRole.stateDisplay();

        //将该游戏角色内部状态进行备份
        //创建管理者对象
        RoleStateCaretaker roleStateCaretaker  = new RoleStateCaretaker();
        roleStateCaretaker.setRoleStatusMemento(gameRole.saveState());

        System.out.println("--------------------大战boss后----------------");
        //损耗严重
        gameRole.fight();
        gameRole.stateDisplay();

        System.out.println("--------------------恢复之前的状态----------------");
        gameRole.recoverState(roleStateCaretaker.getRoleStatusMemento());
        gameRole.stateDisplay();

    }
}

分析:白箱备忘录模式是破坏封装性的。但是通过程序员自律,同样可以在一定程度上实现模式的大部分用意。

10.3.2 “黑箱”备忘录模式

备忘录角色对发起人对象提供一个宽接口,而为其他对象提供一个窄接口,在Java语言中,实现双重接口的办法就是将备忘录类设计成发起人类的成员内部类。

将RoleStateMemento设为GameRole的内部类,从而将RoleStateMemento对象封装在GameRole里面;在外面提供一个标识接口Menento给RoleStateCaretaker及其他对象使用。这样GameRole类看到的就是RoleStateMenento所有的接口,而RoleStateCaretaker及其他对象看到的仅仅是标识接口Memento所暴露出来的接口,从而维护了封装性。

GameRole类

//游戏角色类(发起人角色)
public class GameRole {
    private int vit; //生命力
    private int atk; //攻击力
    private int def; //防御力

    //初始化内部状态
    public void iniState(){
        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 RoleStatusMemento(vit, atk, def);
    }

    //恢复角色状态
    public void recoverState(Memento memento){
        RoleStatusMemento role = (RoleStatusMemento) memento;
        //将备忘录对象中存储的状态赋值给当前对象的成员
        this.vit=role.getVit();
        this.atk=role.getAtk();
        this.def=role.getDef();
    }

    //展示状态功能
    public void stateDisplay(){
        System.out.println("角色生命力:"+getVit());
        System.out.println("角色攻击力:"+getAtk());
        System.out.println("角色防御力:"+getDef());
    }

    public int getAtk() {
        return atk;
    }

    public int getDef() {
        return def;
    }

    public int getVit() {
        return vit;
    }

    public void setVit(int vit) {
        this.vit = vit;
    }

    public void setAtk(int atk) {
        this.atk = atk;
    }

    public void setDef(int def) {
        this.def = def;
    }

    private class RoleStatusMemento implements Memento{
        private int vit; //生命力
        private int atk; //攻击力
        private int def; //防御力

        public RoleStatusMemento() {
        }

        public RoleStatusMemento(int vit, int def, int atk) {
            this.vit = vit;
            this.def = def;
            this.atk = atk;
        }

        public int getVit() {
            return vit;
        }

        public void setVit(int vit) {
            this.vit = vit;
        }

        public int getAtk() {
            return atk;
        }

        public void setAtk(int atk) {
            this.atk = atk;
        }

        public int getDef() {
            return def;
        }

        public void setDef(int def) {
            this.def = def;
        }
    }
}

Memento类

//备忘录接口,对外提供窄接口
public interface Memento {

}

RoleStateCaretaker类

//备忘录对象管理角色
public class RoleStateCaretaker {

    //声明备忘录类型的变量
    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }
}

Client测试类

public class Client {
    public static void main(String[] args) {
        System.out.println("--------------------大战boss前----------------");
        //创建游戏角色对象
        GameRole gameRole=new GameRole();
        gameRole.iniState();
        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();

    }
}

10.4 优缺点

10.5 使用场景

十一.解释器模式

11.1 概述

定义:
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器所有该标识来解释语言中的句子。

11.2 结构

11.3 案例

【例】设计实现加减法的软件

AbstractExpresstion

//抽象表达式类
public abstract class AbstractExpresstion {

    public abstract int interpret(Context context);

}

Context

//环境角色类
public class Context {
    //定义一个map集合,同来存储变量对应的值
    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);
    }

}

Minus

public class Minus extends AbstractExpresstion{

    //减号左边的表达式
    private AbstractExpresstion left;
    //减号右边的表达式
    private AbstractExpresstion right;

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

    public int interpret(Context context) {
        //将左边表达式的结果进行相减
        return left.interpret(context)-right.interpret(context);
    }

    public String toString() {
        return "("+left.toString()+"-"+right.toString()+")";
    }
}

Plus

public class Plus extends AbstractExpresstion{

    //加号左边的表达式
    private AbstractExpresstion left;
    //加号右边的表达式
    private AbstractExpresstion right;

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

    public int interpret(Context context) {
        //将左边表达式的结果进行相加
        return left.interpret(context)+right.interpret(context);
    }

    public String toString() {
        return "("+left.toString()+"+"+right.toString()+")";
    }
}

Variable

//变量类(封装变量)
public class Variable extends AbstractExpresstion{

    //声明存储变量名的成员变量
    private String name;

    public Variable(String name) {
        this.name = name;
    }

    public int interpret(Context context) {
        //返回变量的值
        return context.getValue(this);
    }

    public String toString(){return name;}


}

Client

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

        //获取抽象语法树
        AbstractExpresstion expresstion =new Minus(a,new Plus(new Minus(b, c), d));

        //解释(计算)
        int result = expresstion.interpret(context);

        System.out.println(expresstion + " = " + result);

    }
}

11.4 优缺点

11.5 使用场景

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

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

相关文章

NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis 翻译

NeRF&#xff1a;将场景表示为用于视图合成的神经辐射场 引言。我们提出了一种方法&#xff0c;该方法通过使用稀疏的输入视图集优化底层连续体场景函数来实现用于合成复杂场景的新视图的最新结果。我们的算法使用全连通&#xff08;非卷积&#xff09;深度网络来表示场景&…

设计模式(一):七大原则

*设计模式的目的* 编写软件过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序(软件),具有更好 1) 代码重用性 (即:相同功能的代码,不用多次编写) 2) 可读性 (即:编程规范性, 便于其他程序员的阅读和理…

【C++ 第十七章】封装 unordered_map / unordered_set

声明&#xff1a;上一章讲解了 哈希结构的原理与实现&#xff0c;本章主要将上一章学过的拉链法的哈希结构封装进 unordered_map / unordered_set&#xff0c;所以需要先学过相关知识&#xff0c;才能更好吸收本章知识 上一章的链接&#xff1a;【C 第十六章】哈希 1. unorder…

Ubuntu24.04 安装向日葵远程访问工具

目录 安装向日葵远程访问工具 解决方案&#xff1a; 1.下载软件包 2.远程Ubuntu桌面控制卡住 卸载向日葵远程访问工具 安装向日葵远程访问工具 安装命令&#xff1a;sudo dpkg -i 文件名.deb sudo dpkg -i SunloginClient_15.2.0.63064_amd64.deb 提示错误如下&#xf…

后端修改资源后重新运行项目了,浏览器刷新资源没更新问题

修改后重启项目&#xff0c;去浏览器刷新&#xff1a; 没有改变&#xff1f; 解决办法&#xff1a; F12去调试器里“网络”工具栏下找到“禁用缓存”按钮即可解决

视频转换成文字的5种方法,看一遍就能学会

视频已成为我们获取信息的重要渠道之一。然而&#xff0c;有时我们更需要将视频中的精华内容以文字形式提取出来&#xff0c;以便进行编辑、整理或分享。今天&#xff0c;就为大家介绍五种视频转换成文字的高效方法&#xff0c;一起来了解下吧。 方法一&#xff1a;口袋视频转换…

如何抠图把背景换成透明怎么做?

要抠图并将背景变为透明&#xff0c;这样做的好处是可以方便地将所选物体从原始图像中分离出来&#xff0c;并在其他背景上自由组合。怎么把图片变成透明底&#xff0c;抠图攻略分享&#xff1a;让你轻松上手抠图&#xff01; 通过抠图和背景透明化&#xff0c;您可以创建更多种…

深入理解微服务中的负载均衡算法与配置策略

负载均衡算法 我们首先来探讨一下默认情况下Ribbon使用的负载均衡算法。有些人可能会说它使用轮询算法&#xff0c;因为在本地测试时&#xff0c;我们经常会看到轮询的效果。然而&#xff0c;简单地依赖这种表面的观察来回答面试题是有风险的。实际上&#xff0c;忽略了深入理解…

Superset 无需登录访问分享的图表

1&#xff0c;进入Superset安装目录找到config.py文件 2&#xff0c;修改config.py中的配置项 添加 PUBLIC_ROLE_LIKE: Optional[str] "Gamma" # Grant public role the same set of permissions as for a selected builtin role. # This is useful if one wants to…

Large Bin Attack 源码调试

Large Bin Attack 分配跟 large bin 有关的 chunk&#xff0c;要经过 fastbin&#xff0c;unsorted bin&#xff0c;small bin 的分配&#xff0c;建议在学习 large bin attack 之前搞清楚 fastbin&#xff0c;unsorted bin 分配的流程。 large bin中双向链表的连接方法&…

五款伪原创文章生成器软件,为创作者快速生成高质量内容

在内容为王的时代&#xff0c;创作者们面临着巨大的压力&#xff0c;需要不断地产出高质量、有深度的文章。在这个过程中&#xff0c;伪原创文章生成器软件成为了许多创作者的得力助手。本文将为你详细介绍5款伪原创文章生成器软件&#xff0c;帮助你快速生成高质量内容。 一、…

vue part4

收集表单数据 v-model label直接包住input不用关联也可以获取焦点 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>收集表单数据</title><script type"text/javascript" src&quo…

SpringBoot校园万能墙系统的设计与实现97395

目 录 1 绪论 1.1研究背景与意义 1.2研究现状 1.3论文结构与章节安排 2 相关技术介绍 2.1 springboot框架介绍 2.2 JavaScript 2.3 Mysql数据库 2.4 Vue.js 主要功能 3 系统分析 3.1 可行性分析 3.1.1 技术可行性分析 3.1.2 经济可行性分析 3.1.3 法律可行性分析…

“领导让我帮忙买30杯奶茶,实际花费535元,但领导却只转了500元,我该如何提醒领导转我35元的差额?”

在职场中&#xff0c;我们时常会遇到一些让人哭笑不得的小事&#xff0c;它们虽小&#xff0c;却足以反映出职场中的微妙关系和处事哲学。 一位行政朋友曾发帖称&#xff1a;“我是一名5年工作经验的企业行政助理&#xff0c;也不是小白。但有一次&#xff0c;业务部门领导让我…

【机器学习】嘿马机器学习(科学计算库)第4篇:Matplotlib,学习目标【附代码文档】

本教程的知识点为&#xff1a;机器学习&#xff08;常用科学计算库的使用&#xff09;基础定位 机器学习概述 机器学习概述 1.5 机器学习算法分类 1 监督学习 机器学习概述 1.7 Azure机器学习模型搭建实验 Azure平台简介 Matplotlib 3.2 基础绘图功能 — 以折线图为例 1 完善原…

为什么每个Java开发者都应该掌握CompletableFuture?深入探索这一强大的并发工具!

文章目录 1 如何正确处理异步任务的异常情况&#xff1f;2 如何设置 CompletableFuture 的超时时间&#xff1f;3 如何取消正在执行的CompletableFuture任务&#xff1f; 1 如何正确处理异步任务的异常情况&#xff1f; 想象一下&#xff0c;用餐厅的例子来比喻 CompletableFut…

计算机组成与设计 - 1.7 功耗墙 - 1.8 单处理器向多处理器的转变 - 1.9 基准

1.7 功耗墙 25 年间 1ntel x86 八代微处理器的时钟频率和功耗 。 奔腾 4 处理器时钟频率和功耗提高很大 &#xff0c;但是性能提升不大 。 Prescott 发热问题导致奔腾 4 处理器的生产线被放弃 。 Core 2 生产线恢复使用低时钟频率的简单流水线和片上多处理器 。 Core i5 采用同…

前端常见问题

一、<!DOCTYPE html>作用 <!DOCTYPE>是html文档的第一行&#xff0c;用于声明文档的类型&#xff0c;它会告诉浏览器要用哪一种HTML规范来渲染文档&#xff0c;确保正确渲染页面。 二、src与 href 的区别 &#xff08;一&#xff09;、请求资源类型的不同 在请…

研究生如何利用 ChatGPT 帮助开展日常科研工作?

研究生可以通过以下几种方式利用 ChatGPT 来帮助开展日常科研工作&#xff1a; 文献综述和研究方向&#xff1a;ChatGPT 可以帮助研究生快速了解某一领域的研究现状和热点问题。通过提供相关的文献综述、研究趋势和技术细节&#xff0c;ChatGPT 可以协助确定研究方向和课题。 …

来抄作业!企业财务报表还可以做出这样的可视化效果

从繁琐的手工记账到智能化的数据分析&#xff0c;每一步都标志着企业向更加高效、精准的管理模式迈进。大家可以想象一下&#xff0c;将复杂多变的财务数据以直观、动态的形式展现在眼前的大屏之上&#xff0c;会是一种怎样的体验&#xff1f; 这里就要说到使用山海鲸报表工具搭…