🌐 行为型模式介绍及代码实现

一、行为型模式(Behavioral Patterns)

1.1 模板方法(Template Method)

模板方法允许一些步骤延迟到子类中实现。这种模式允许子类在不改变算法结构的情况下,重新定义算法中的某些步骤

--------------------------------------------场景模拟----------------------------------------------

比如小帅的母亲需要做红桃粿(一种潮汕小吃),为了做出它需要用水和面,洗切蘑菇,还需要用力揉面粉成型,这个步骤就比较费力,就由小帅完成,后面就是准备好红桃粿的模具做成型即可

---------------------------------------------代码实现---------------------------------------------

1.定义一个制作模板类 MakePeachTemplate

java 复制代码
/**
 * 定义模板
 */
public abstract class MakePeachTemplate {

    /**
     * 定义算法:  定义好了模板
     * 父类可以实现某些步骤
     * 留关键给子类
     */
    public void make(){
        //定义算法步骤
        wash();   
        kneadDough();
        complete();
    }
    
    public void wash(){
        System.out.println("用水和面+洗切蘑菇");
    };
    
    //关键步骤给子类实现
    public abstract void kneadDough();
    
    public  void complete(){
        System.out.println("完成红桃粿");
    };
    
}

2.定义一个实现类AutoMakePeachMachine

java 复制代码
public class AutoMakePeachMachine extends MakePeachTemplate {

    @Override
    public void kneadDough() {
        System.out.println("用力揉面");
    }
    
}

3.测试类测试

Java 复制代码
public class MainTest {
    public static void main(String[] args) {
        AutoMakePeachMachine makePeachMachine = new AutoMakePeachMachine();
        makePeachMachine.make();
    }
}

1.2 策略(Strategy)模式

策略模式定义了一系列算法,并将每个算法封装成一个独立的策略类。这些策略类可以相互替换,使得算法的选择可以在运行时动态改变。

--------------------------------------------场景模拟----------------------------------------------

话说诸葛亮北伐曹操的时候,他就进攻路线有很多种,就会有很多进攻策略

---------------------------------------------代码实现---------------------------------------------

1.定一个类 XingFuHanChamber

Java 复制代码
public class XingFuHanChamber {
    private NorthernExpedition northernExpedition;

    public void setGameStrategy(NorthernExpedition northernExpedition) {
        this.northernExpedition = northernExpedition;
    }

    public void northernBegin(){
        System.out.println("北伐开始.....");

        northernExpedition.warStrategy();
        System.out.println("兴复汉室-----");
    }
}

2.定义一个策略接口 NorthernExpedition

Java 复制代码
public interface NorthernExpedition {
    void warStrategy();
}

3.定义一个策略的具体实现类 AttackQiShan、AttackChangAn

Java 复制代码
public class AttackQiShan implements NorthernExpedition {
    @Override
    public void warStrategy() {
        System.out.println("攻打祁山...");
    }
}

public class AttackChangAn implements NorthernExpedition {
    @Override
    public void warStrategy() {
        System.out.println("子午谷奇谋--攻打长安");
    }
}

4.测试类测试

java 复制代码
public class MainTest {
    public static void main(String[] args) {
        XingFuHanChamber gnr = new XingFuHanChamber();
        gnr.setGameStrategy(new AttackQiShan());
        gnr.northernBegin();
    }
}
java 复制代码
public class MainTest {
    public static void main(String[] args) {
        XingFuHanChamber gnr = new XingFuHanChamber();
        gnr.setGameStrategy(new AttackChangAn());
        gnr.northernBegin();
    }
}

1.3 状态(State)模式

状态允许对象在内部状态改变时改变其行为。状态模式将对象的状态和行为解耦,使得对象可以根据不同的状态执行不同的行为。

--------------------------------------------场景模拟----------------------------------------------

话说小帅进行一场校园篮球比赛,刚开始心不在焉总是丢分,后来教练步骤了进攻策略有了进步但还是落后,再后来帅哥的女神来观看比赛,这时候帅哥直接乔丹附体直接扭转比赛

---------------------------------------------代码实现---------------------------------------------

1.定一个状态接口TFBoysState

java 复制代码
/**
 * 抽象状态
 */
public interface TFBoysState {
    void playBasketball();

    //切换到下一个状态
    TFBoysState next();
}

2.定义状态环境类TFBoys

java 复制代码
public class TFBoys {

    private TFBoysState TFBoysState;

    public void setTeamState(TFBoysState TFBoysState) {
        this.TFBoysState = TFBoysState;
    }

    public void startGame(){
        //状态不同会导致不同的比赛结果
        TFBoysState.playBasketball();
    }


    //下一个状态
    void nextState(){
        TFBoysState = TFBoysState.next();
    }
}

3.定义三种不同的比赛状态类 AbsentMindedState、TriangleState、BlessednessState

Java 复制代码
public class AbsentMindedState implements TFBoysState {
    @Override
    public void playBasketball() {
        System.out.println("心不在焉---持续丢分:落后20分");
    }
    @Override
    public TFBoysState next() {
        return new TriangleState();
    }
}

public class TriangleState implements TFBoysState {

    @Override
    public void playBasketball() {
        System.out.println("三角进攻----丢分不那么严重:落后10分");
    }

    @Override
    public TFBoysState next() {
        return new BlessednessState();
    }
}

public class BlessednessState implements TFBoysState {
    @Override
    public void playBasketball() {
        System.out.println("女神来了...扭转局势:绝杀比赛");
    }

    @Override
    public TFBoysState next() {
        return new AbsentMindedState();
    }
}

4.测试类测试

java 复制代码
public class MainTest {
    public static void main(String[] args) {

        TFBoys TFBoys = new TFBoys();
        TFBoysState state = new AbsentMindedState();
        TFBoys.setTeamState(state);
        TFBoys.startGame();

        state = state.next();
        TFBoys.setTeamState(state);
        TFBoys.startGame();

        //状态需要维护自己的切换逻辑
        state = state.next();
        TFBoys.setTeamState(state);
        TFBoys.startGame();
    }
}

由此可以看出状态模式和策略模式不同的地方就是状态的切换有不同的效果

1.4 中介者(Mediator)模式

在中介者模式中,各个对象不再直接相互通信,而是通过与中介者对象进行交互来传递消息和执行操作。中介者对象负责处理对象之间的复杂关系和通信逻辑,从而降低了系统的复杂性和耦合度。

--------------------------------------------场景模拟----------------------------------------------

话说小帅打完比赛回家来到了一个十字路口,这时候需要等红绿灯,这红绿灯的作用就相当于于一个中介者,管理不同的人们通过这个路口

---------------------------------------------代码实现---------------------------------------------

1.定一个抽象人类类Humans (通过马路)

java 复制代码
public abstract class Humans {

    //过马路
    abstract void cross();

    //到达对面
    abstract void reach();

}

2.定义应该交通规则类 TrafficLight

Java 复制代码
public class TrafficLight {

    private boolean allow = true;

    //接受请求...
    public void acceptRequest(Humans humans, String action){
        if("cross".equals(action)||"land".equals(action)){
            //
            if(allow == true){
                System.out.println("绿灯---可以通过");
                allow = false;
            }else {
                System.out.println("红灯---禁止通过");
            }
        }
        if("reach".equals(action)){
            allow = true;
        }
        
    }
}

3.定两个通过类 ShuaiGeDriver

java 复制代码
public class ShuaiGe extends Humans {

    TrafficLight trafficLight;

    public void setControlTower(TrafficLight trafficLight) {
        this.trafficLight = trafficLight;
    }

    @Override
    void cross() {
        System.out.println("帅哥要嚣张的走过马路咯");
        trafficLight.acceptRequest(this,"cross");
    }
    
    @Override
    void reach() {
        System.out.println("帅哥安全的到达马路对面");
        trafficLight.acceptRequest(this,"reach");
    }
}

public class Driver extends Humans {

    TrafficLight trafficLight;

    public void setControlTower(TrafficLight trafficLight) {
        this.trafficLight = trafficLight;
    }

    @Override
    void cross() {
        System.out.println("司机请求通过马路");
        trafficLight.acceptRequest(this,"cross");

    }

    @Override
    void reach() {

        System.out.println("司机安全的通过马路");
        trafficLight.acceptRequest(this,"cross");
    }
}

4.测试类测试

java 复制代码
public class MainTest {

    public static void main(String[] args) {
        ShuaiGe shuaiGe = new ShuaiGe();
        Driver driver = new Driver();

        TrafficLight tower = new TrafficLight();
        shuaiGe.setControlTower(tower);
        driver.setControlTower(tower);

        shuaiGe.cross();
        shuaiGe.reach();
        driver.cross();
        driver.cross();

    }
}

1.5 观察者(Observer)模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当这个主题对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己的状态。

--------------------------------------------场景模拟----------------------------------------------

比如小帅在直播平台开始了首秀,他人气不佳,就购买了一些机器人,当小帅直播的时候机器人就进入了直播间,这就体现了观察者模式,一旦小帅开播,就把消息通知到机器人,告诉它们进入直播间

---------------------------------------------代码实现---------------------------------------------

1.定义一个直播功能抽象类 AbstractTikToker (有增加粉丝,和通知粉丝)

java 复制代码
public abstract class AbstractTikToker {

    //添加粉丝
    abstract void addFans(AbstractFans fans);

    //通知粉丝
    abstract void notifyFans(String msg);
}

2.定义一个实现类 XiaoShuai (主播小帅,有直播功能)

java 复制代码
/**
 * 主播
 * 双向观察
 */
public class XiaoShuai extends AbstractTikToker{

    //观察者的核心
    List<AbstractFans> fansList = new ArrayList<>();

    void startSell() {
        System.out.println("小帅开始直播了");
        notifyFans("我开始直播了快来观看");
    }
    void endSell() {
        System.out.println("小帅结束直播了");
        notifyFans("我结束直播了请说晚安");
    }

    @Override
    void addFans(AbstractFans fans) {
        fansList.add(fans);
    }

    @Override
    void notifyFans(String msg) {
        //所有粉丝拿来通知
        for (AbstractFans fans : fansList) {
            fans.acceptMsg(msg);
        }
    }
}

3.定义一个抽象观察者 AbstractFans

java 复制代码
public abstract class AbstractFans {
    abstract void acceptMsg(String msg);

    void follow(AbstractTikToker tikToker){
        tikToker.addFans(this);
    };
}

4.定义实现类 HumanFansRobotFans (真人粉丝,还有机器粉丝)

java 复制代码
public class HumanFans extends AbstractFans {
    @Override
    void acceptMsg(String msg) {
        System.out.println("真人:"+msg);
    }
}

public class RobotFans extends AbstractFans {
    @Override
    void acceptMsg(String msg) {
        System.out.println("机器人:"+msg);
    }
}

5.测试类测试

java 复制代码
public class MainTest {
    public static void main(String[] args) {

        XiaoShuai lei = new XiaoShuai();
        lei.startSell();
        RobotFans robotFans = new RobotFans();
        RobotFans robotFansTwo = new RobotFans();
        RobotFans robotFansThree = new RobotFans();
        robotFans.follow(lei);
        robotFansTwo.follow(lei);
        robotFansThree.follow(lei);

        HumanFans humanFans = new HumanFans();
        humanFans.follow(lei);
        System.out.println("-------------");
        lei.endSell();
    }
}

1.6 备忘录(Memento)模式

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

--------------------------------------------场景模拟----------------------------------------------

小帅在写代码,然后提交了一次代码,又写了代码 ,又提交了第二次代码,发现代码写错了,回滚到第一次代码,这时候就可以使用备忘录模式回滚

---------------------------------------------代码实现---------------------------------------------

1.定义一个类CodeRecord

java 复制代码
@Data
public class CodeRecord {
    Integer id; //代表生成记录的id
    Integer code;//代码

}

2.定义一个类GitServer

java 复制代码
public class GitServer {

    //管理备忘录信息的
    Map<Integer, CodeRecord> records = new HashMap<>();
    int i = 1;

    void add(CodeRecord codeRecord){
        codeRecord.setId(i++);
        records.put(codeRecord.id, codeRecord);
    }

    XiaoShuai getRecord(Integer id) throws Exception {
        CodeRecord codeRecord = records.get(id);
        //获取到备忘录里面的内容以后还要逆转
        XiaoShuai xiaoShuai = new XiaoShuai();
        //BeanUtils:工具类,属性对拷
        BeanUtils.copyProperties(xiaoShuai, codeRecord);

        return xiaoShuai;
    }

}

3.定义一个类XiaoShuai

java 复制代码
@Data
public class XiaoShuai {

    Integer id;//代码版本号
    Integer code;//代码

    GitServer gitServer = new GitServer();

    void saveCodeRecord() throws Exception {
        System.out.println("保存当前代码");
        CodeRecord codeRecord = new CodeRecord();
        //当前游戏信息保存到备忘录
        BeanUtils.copyProperties(codeRecord,this);
        //
        gitServer.add(codeRecord);
    }

    XiaoShuai getFromMemento(Integer id) throws Exception {
        System.out.println("获取版本代码信息");
        XiaoShuai record = gitServer.getRecord(id);
        return record;
    }

    //写代码
    void makeCode(){
        int i = new Random().nextInt();
        System.out.println("写代码::--"+i);
        id = i;
        code = i;

    }
}

4.测试类测试

java 复制代码
public class MainTest {
    public static void main(String[] args) throws Exception {
        XiaoShuai xiaoShuai = new XiaoShuai();
        xiaoShuai.makeCode();
        xiaoShuai.saveCodeRecord();
        xiaoShuai.makeCode();
        xiaoShuai.makeCode();
        xiaoShuai.saveCodeRecord();
        XiaoShuai fromMemento = xiaoShuai.getFromMemento(1);
        fromMemento.makeCode();
    }
}

1.7 命令(Command)模式

命令模式允许将请求封装成一个对象,从而使得可以参数化客户端对象,队列操作,记录日志,支持撤销等操作。在命令模式中,命令被封装为一个对象,这个对象包含了具体的操作及其相关参数,并且提供了一个执行操作的方法。通过将命令封装成对象,客户端可以通过不同的命令对象来进行不同的操作,从而实现了命令的参数化。命令模式常用于实现日程安排、任务队列等场景。

--------------------------------------------场景模拟----------------------------------------------

话说小帅写代码写累了,他就去看会电视,这时候电视遥控器就是编辑一堆的命令模式,只需要调用者小帅按下相对应的命令,就能成功执行

---------------------------------------------代码实现--------------------------------------------- 1.定义一个接口Command

Java 复制代码
public interface  Command {

    /**
     * 命令的执行方法
     */
    void execute();

}

2.定义一个命令接受者(执行者)类 TVRemoteControl

Java 复制代码
public class TVRemoteControl {
    public void turnUp(){
        System.out.println("调大电视音量");
    }
    public void change(){
        System.out.println("更换频道");
    }
}

3.定义命令的具体执行逻辑类 TurnUpCommand、ChangeCommand

Java 复制代码
public class TurnUpCommand implements Command{
    private TVRemoteControl turnUp = new TVRemoteControl();
    @Override
    public void execute() {
        System.out.println("调大音量咯-------");
        turnUp.turnUp();
    }
}


public class ChangeCommand implements Command{

    private TVRemoteControl receiver = new TVRemoteControl();

    @Override
    public void execute() {
        System.out.println("更换频道---还珠格格");
        receiver.change();
    }
}

4.定一个一个调用者小帅类 XiaoShuai

Java 复制代码
public class XiaoShuai {
    Command command;

    public void call(){
        command.execute();
    }
    public void setCommand(Command command) {
        this.command = command;
    }
}

5.测试类测试

Java 复制代码
public class MainTest {

    public static void main(String[] args) {
        XiaoShuai invoker = new XiaoShuai();
        invoker.setCommand(new TurnUpCommand());
        invoker.call();
    }
}
Java 复制代码
public class MainTest {

    public static void main(String[] args) {
        XiaoShuai invoker = new XiaoShuai();
        invoker.setCommand(new ChangeCommand());
        invoker.call();
    }
}

1.8 迭代器(Iterator)模式

迭代器模式用于提供一种顺序访问集合对象元素的方法,而不需要暴露其内部表示。迭代器模式是将迭代器的责任分离出来,使得集合对象可以专注于自身的管理,而迭代器则负责提供一种统一的方式来访问集合对象中的元素。

--------------------------------------------场景模拟----------------------------------------------

话说小帅在看完电视的时候发现旁边有一个编程机器人,输入响应的编程指令就可以完成规定的编程动作,而且遥控器上还有上一个动作,下一个动作等,就相当于迭代的作用,我们去指定相对于的指令然后遥控器就迭代出对应的动作

---------------------------------------------代码实现---------------------------------------------

1.定义一个机器人抽象类 Robot

java 复制代码
public abstract class Robot {

    private List<String> robotAction = new ArrayList<>();

    void addAction(String name) {
        robotAction.add(name);
    }

    ;

    void moveAction(String name) {
        robotAction.remove(name);
    }

    ;

    public Itr getIterator() {
        return new Iterator();
    }

    /**
     * 具体迭代器
     */
    class Iterator implements Itr {

        private int cursor = 0; //当前指针

        public boolean hasNext() {
            return cursor < robotAction.size();
        }

        public String next() {
            //第一次调用返回第一个数据
            //下一次再调用自动访问下一个数据
            String s = robotAction.get(cursor);
            cursor++;
            return s;
        }

        @Override
        public String firstAction() {
            return robotAction.get(0);
        }

        @Override
        public String current() {
            return robotAction.get(robotAction.size() - 1);
        }
    }

    interface Itr {
        boolean hasNext();

        String next();

        String firstAction();

        String current();
    }

}

2.测试类测试

Java 复制代码
public class MainTest {
    public static void main(String[] args) {
        MaYuCheng cheng = new MaYuCheng();
        cheng.addAction("跳舞");
        cheng.addAction("唱歌");
        cheng.addAction("前进");

        Robot.Itr itr = cheng.getIterator();
        String firstAction = itr.firstAction();
        System.out.println("第一个动作"+":"+firstAction);
        String current = itr.current();
        System.out.println("第三个动作"+":"+current);
        while (itr.hasNext()){
            String next = itr.next();
            System.out.println("还有动作"+":"+next);
        }
    }
}

迭代器模式多用于集合的迭代,像List、Map,迭代器也是接口

总结

行为型模式主要关注对象之间的交互和职责分配。行为型模式涉及到对象的行为和算法,用于描述系统在运行时的动态行为。 行为型模式的目的是通过定义对象之间的通信方式,来实现系统中复杂的行为和控制流程。常见的行为型模式包括策略模式、观察者模式、命令模式、状态模式等。 这些模式通过抽象和封装对象的行为,提供了一种灵活和可重用的方式来处理对象之间的交互。它们有助于提高系统的可维护性、可扩展性和灵活性,使得系统能够更好地应对变化和需求的增长。

相关推荐
许野平42 分钟前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
暗黑起源喵2 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
齐 飞2 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
LunarCod3 小时前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
码农派大星。3 小时前
Spring Boot 配置文件
java·spring boot·后端
杜杜的man4 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*4 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu4 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s4 小时前
Golang--协程和管道
开发语言·后端·golang
为什么这亚子4 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算