设计模式初识(四)行为型模式

行为型模式

  • 行为型模式关注点在于"如何运行对象/类";
  • 行为型模式用来描述程序在运行时复杂的流程控制;
  • 描述多个类或对象之间怎样互相协作共同完成单个对象都无法单独完成的任务,设计算法与对象间职责的分配;
  • 行为型模式分为类行为模式对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。

模板方法模式

  • 在模板模式中,一个抽象类公开定义了执行它的方法的方式模板。它的子类可以按需重写方法实现,但调用将以抽象类中定义的方式进行;

例子

以做饭举例

  • 模板类
package com.vleus.design.behavioral.template;

/**
 * @author vleus
 * @date 2021年06月06日 15:49
 */
public abstract class CookieTemplate {

    /**
     * 定义算法:定义好的模板,关键性步骤留给子类实现
     */
    public void cook() {
        //定义算法步骤
        heating();
        addFood();
        addSalt();
        stirfry();
        end();
    }

    //加热方法
    public void heating() {
        System.out.println("准备开火。。。");
    }

    //添加食物
    public abstract void addFood();


    //加盐
    public abstract void addSalt();

    //翻炒
    public void stirfry() {
        System.out.println("翻炒中。。。");
    }

    //出锅
    public void end() {
        System.out.println("出锅。。。。");
    }

}
  • 子类实现模板类
package com.vleus.design.behavioral.template;

/**
 * @author vleus
 * @date 2021年06月06日 15:53
 */
public class AutoCookMachine extends CookieTemplate{

    @Override
    public void addFood() {
        System.out.println("放了三根娃娃菜。。。");
    }

    @Override
    public void addSalt() {
        System.out.println("放了一勺盐。。。");
    }
}
  • 测试类
package com.vleus.design.behavioral.template;

/**
 * @author vleus
 * @date 2021年06月06日 15:54
 */
public class MainTest {

    public static void main(String[] args) {

        AutoCookMachine autoCookMachine = new AutoCookMachine();

        autoCookMachine.cook();

    }
}
  • 运行结果
    在这里插入图片描述

模板方法使用场景

  • Spring的整个继承体系都基本用到模板方法:
    • BeanFactory:getBean-A-B-C-D;
  • JdbcTemplate、RedisTemplate都允许再扩展

策略模式

概念:策略(Strategy)模式定义了一系列算法,并将每个算法封装起来,使得它们可以相互替换,且算法的变化不会影响使用算法的客户。属于对象行为模式

  • 抽象策略类(Strategy);
  • 具体策略(Concrete Strategy);
  • 环境类:持有一个策略类的引用,最终给客户端调用;

例子

以RNG的打游戏的策略为例
环境类,持有策略引用

package com.vleus.design.behavioral.strategy;

/**
 * @author vleus
 * @date 2021年06月06日 16:04
 */
public class TeamRNG {

    //抽取游戏策略算法,并进行引用
    private GameStrategy gameStrategy;

    public void setGameStrategy(GameStrategy gameStrategy) {
        this.gameStrategy = gameStrategy;
    }

    public void startGame() {

        System.out.println("全军出击。。。");

        //使用游戏套路
        gameStrategy.warStrategy();

        System.out.println("Victory。。。。。");
    }
}

抽象策略类,定义相关策略方法

package com.vleus.design.behavioral.strategy;

public interface GameStrategy {

    //游戏策略方法
    void warStrategy();
}

抽象策略类的实现1

package com.vleus.design.behavioral.strategy;

/**
 * @author vleus
 * @date 2021年06月06日 16:07
 */
public class UziStrategy implements GameStrategy{
    @Override
    public void warStrategy() {
        System.out.println("uzi莽夫式打法获取胜利。。。。");
    }
}

抽象策略类的实现2

package com.vleus.design.behavioral.strategy;

/**
 * @author vleus
 * @date 2021年06月06日 16:07
 */
public class SteadyGameStrategy implements GameStrategy{

    @Override
    public void warStrategy() {
        System.out.println("稳健运营,蚕食对手获取胜利。。。");
    }
}

测试类

package com.vleus.design.behavioral.strategy;

/**
 * @author vleus
 * @date 2021年06月06日 16:08
 */
public class MainTest {

    public static void main(String[] args) {
        TeamRNG teamRNG = new TeamRNG();

        teamRNG.setGameStrategy(new UziStrategy());

        teamRNG.startGame();

        System.out.println("----------------------");

        teamRNG.setGameStrategy(new SteadyGameStrategy());
        teamRNG.startGame();
    }
}

使用场景

  • Spring的InstantiationStrategy;
  • 线程池拒绝策略;
    。。。。

状态模式

概念:状态模式,对有状态的对象,把负责的"判断逻辑"提取到不同的状态对象中,允许状态对象在其内部状态发生改变的时候改变其行为;

  • 环境类角色;
  • 抽象状态角色;
  • 具体状态角色

抽象状态类

package com.vleus.design.behavioral.state;

public interface TeamState {

    //玩游戏的状态
    void playGame();

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

状态实现类1

package com.vleus.design.behavioral.state;

/**
 * @author vleus
 * @date 2021年06月06日 16:19
 */
public class VocationState implements TeamState{

    @Override
    public void playGame() {
        System.out.println("在三亚度假,真舒服,不想打游戏。。。");
    }

    //切换到下一个状态
    @Override
    public TeamState next() {
        return new EatBeefNoodlesState();
    }
}

状态实现类2

package com.vleus.design.behavioral.state;

/**
 * @author vleus
 * @date 2021年06月06日 16:20
 */
public class EatBeefNoodlesState implements TeamState{

    @Override
    public void playGame() {
        System.out.println("恰牛肉面恰饱饱。。。。");
    }

    @Override
    public TeamState next() {
        return new MatchState();
    }
}

状态实现类3

package com.vleus.design.behavioral.state;

/**
 * @author vleus
 * @date 2021年06月06日 16:18
 */
public class MatchState implements TeamState{

    @Override
    public void playGame() {
        System.out.println("全力以赴打比赛...");
    }

    @Override
    public TeamState next() {
        return new VocationState();
    }
}

环境类调用

package com.vleus.design.behavioral.state;

/**
 * @author vleus
 * @date 2021年06月06日 16:17
 * @desc 环境类
 */
public class SktTeam {

    private TeamState teamState;

    public void setTeamState(TeamState teamState) {
        this.teamState = teamState;
    }

    void startGame() {
        //状态不同可能会导致不同的游戏结果
        teamState.playGame();
    }

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

测试类

package com.vleus.design.behavioral.state;

/**
 * @author vleus
 * @date 2021年06月06日 16:20
 */
public class MainTest {

    public static void main(String[] args) {

        SktTeam sktTeam = new SktTeam();
        VocationState state = new VocationState();
        sktTeam.setTeamState(state);

        sktTeam.startGame();
        sktTeam.nextState();
        sktTeam.startGame();
        sktTeam.nextState();
        sktTeam.startGame();
    }
}

中介者模式

网状变星状
在这里插入图片描述
概念:用一个中介对象来封装一系列的对象交互,中介者使得各个对象之间不需要显式地互相调用,减少对象间混乱的依赖关系,从而使其耦合松散,而且可以独立地改变他们之间的交互。属于对象行为模式。

观察者模式

概念:定义对象间的一种一对多依赖关系,使得当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又被成为发布-订阅模式。
核心:被观察对象维护观察对象的引用集合,发生变化的时候通知每一个观察对象即可,就拿tiktok的关注主播为例

  • 抽象主播类:
package com.vleus.design.behavioral.observer;

/**
 * @author vleus
 * @date 2021年06月06日 17:50
 */
public abstract class AbstractTikToker {

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

    //通知粉丝
    abstract void notifyFans(String msg);
}
  • 美女主播实现类
package com.vleus.design.behavioral.observer;

import com.vleus.design.structural.flyweight.AbstractWaitressFlyweight;

import java.util.ArrayList;
import java.util.List;

/**
 * @author vleus
 * @date 2021年06月06日 17:52
 */
public class MMTikToker extends AbstractTikToker {

    List<AbstractFans> fansList = new ArrayList<>();

    void startSell() {
        System.out.println("主播开始卖货了。。。");
        notifyFans("我开始卖货了,卖茅台。。。");
    }

    void enbSell() {

        System.out.println("主播货卖完了。。。");
        notifyFans("茅台已经卖完了");
    }

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

    /**
     * 通知粉丝
     */
    @Override
    void notifyFans(String msg) {
        //遍历粉丝
        for (AbstractFans abstractFans : fansList) {
            abstractFans.acceptMsg(msg);
        }
    }
}
  • 抽象粉丝类
package com.vleus.design.behavioral.observer;

/**
 * @author vleus
 * @date 2021年06月06日 17:52
 */
public abstract class AbstractFans {

    abstract void acceptMsg(String msg);

    void follow(AbstractTikToker tikToker) {
        //主播增加粉丝
        tikToker.addFans(this);
    }
}
  • 粉丝实现类
package com.vleus.design.behavioral.observer;

/**
 * @author vleus
 * @date 2021年06月06日 17:57
 */
public class HumanFans extends AbstractFans{

    @Override
    void acceptMsg(String msg) {
        System.out.println("粉丝说主播说:" +msg);
    }
}

测试类

package com.vleus.design.behavioral.observer;

/**
 * @author vleus
 * @date 2021年06月06日 17:56
 */
public class MainTest {

    public static void main(String[] args) {

        MMTikToker mmTikToker = new MMTikToker();

        mmTikToker.startSell();

        HumanFans humanFans1 = new HumanFans();
        HumanFans humanFans2 = new HumanFans();
        HumanFans humanFans3 = new HumanFans();

        humanFans1.follow(mmTikToker);
        humanFans2.follow(mmTikToker);
        humanFans3.follow(mmTikToker);

        System.out.println("---------------------------");

        mmTikToker.enbSell();
    }
}

使用场景

  • Spring事件通知机制;
  • 响应式编程;
  • Vue的双向绑定核心

备忘录模式

概念:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要的时候能够将对象恢复成原先保存的状态。该模式又称为快照模式。对象行为型模式。

  • 发起人角色:记录当前时刻的内部状态信息
  • 备忘录角色:负责存储发起人的内部装态;
  • 管理者角色:对备忘录进行管理,提供保存于获取备忘录的功能,但其不能对备忘录的内容进行访问与修改;

举例

以打游戏举例,游戏服务器会保存角色的某些状态

  • 发起人角色
package com.vleus.design.behavioral.memento;

import lombok.Data;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.Random;

/**
 * @author vleus
 * @date 2021年06月07日 22:47
 * 游戏者,游戏发起人
 * @当前游戏信息
 */
@Data
public class UziGamer {

    Integer coin; //剩余金币

    Integer hp; //血量

    Integer mp; //蓝量

    Integer level; //等级

    //以上的是内部状态,需要记录保存的信息
    GameServer gameServer = new GameServer();

    //保存游戏记录
    void saveGameRecord() throws InvocationTargetException, IllegalAccessException {
        System.out.println("正在保存当前记录。。。");
        GameRecord gameRecord = new GameRecord();
        //当前游戏信息保存到备忘录
        BeanUtils.copyProperties(gameRecord,this);

        gameServer.add(gameRecord);
    }

    //从备忘录获取游戏历史存档
    UziGamer getFromMemento(Integer id) {
        System.out.println("获取历史存档信息。。。");
        UziGamer record = gameServer.getRecord(id);

        return record;
    }

    //玩游戏
    void playGame() {

        int i = new Random().nextInt();
        System.out.println("打怪,升级,赚金币,打怪,爆史诗。。。" + i);
        coin = i;
        hp = i;
        mp = i;
        level = i;
    }

    void exitGame() throws InvocationTargetException, IllegalAccessException {
        System.out.println("游戏真垃圾,我退游了。。。");
        saveGameRecord();
    }

}
  • 备忘录角色,记录某些信息
package com.vleus.design.behavioral.memento;

import lombok.Data;

/**
 * @author vleus
 * @date 2021年06月07日 22:53
 */
@Data
public class GameRecord {

    Integer id;

    Integer coin; //剩余金币

    Integer hp; //血量

    Integer mp; //蓝量

    Integer level; //等级

    //获取当前备忘录信息
    void getCurrent() {
        System.out.println("coin: " + coin);
    }


}
  • 管理者角色
package com.vleus.design.behavioral.memento;

import java.util.HashMap;
import java.util.Map;

/**
 * @author vleus
 * @date 2021年06月07日 22:56
 * 管理者,记录所有的状态
 */
public class GameServer {

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

    void add(GameRecord gameRecord) {
        records.put(i++, gameRecord);
    }

    UziGamer getRecord(Integer id) {
        GameRecord gameRecord = records.get(id);

        //获取到备忘录里面的内容还需要逆转
        UziGamer uziGamer = new UziGamer();
        uziGamer.setCoin(gameRecord.coin);
        uziGamer.setHp(gameRecord.hp);
        uziGamer.setLevel(gameRecord.level);
        uziGamer.setMp(gameRecord.mp);

        return uziGamer;
    }
}
  • 测试类
package com.vleus.design.behavioral.memento;

import java.lang.reflect.InvocationTargetException;

/**
 * @author vleus
 * @date 2021年06月07日 23:03
 * 1、备忘录的设计(提取属性);
 * 2、备忘录对象和原对象的互转操作(BeanUtils属性对拷)
 *  序列化
 *  保存数据库
 */
public class MainTest {

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {

        UziGamer uziGamer = new UziGamer();

        uziGamer.playGame();
        uziGamer.saveGameRecord();

        uziGamer.playGame();

        uziGamer.playGame();

        uziGamer.saveGameRecord();

        UziGamer fromMemento = uziGamer.getFromMemento(1);

        fromMemento.playGame();
    }
}

使用场景

  • 游戏存档
  • 数据库保存事务;
  • session活化钝化;
    。。。

解释器模式

。。。不多说了,挺难的,不常见;

命令模式

概念:将一个请求封装为一个对象,使得发出请求的责任和执行请求的责任分开。

类似MVC编码,就不介绍了,Controller,Service,Dao

迭代器模式

  • 提供一个对象(迭代器)来顺序访问聚合对象(迭代数据)中的一系列数据,而不暴露聚合对象的内部表示。对象行为型模式。

访问者(Visitor)模式

访问者模式:将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用域这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将数据的操作与数据结构进行分离。

责任链模式

  • 责任链模式:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。属于对象行为型模式。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值