从 Forces 开始分析责任链模式:「写一个 Discord 对话机器人」

本文通过一个实战案例,介绍了如何使用责任链模式设计一个Discord机器人,应对不断变化的功能需求。首先,从面向对象分析出发,设计出初版程序,然后识别出代码中的问题,如行为变动性、维护性和灵活性。通过责任链模式,将行为变种封装到单独的处理器类中,实现了解耦和灵活性。最后,通过模板方法进一步减少了重复代码,提高了代码的可维护性。
摘要由CSDN通过智能技术生成

目录

前言

你收到了一份需求

面向对象分析 (OOA)

初版程式实作

察觉 Forces

套用责任链模式 (OOD)

封装变动之处 (Encapsulate what varies)

萃取共同行为 (Abstract common behaviors)

委派/複合 (Delegation / Composition)

重构出第二版程式码

责任链模式总结

责任链模式中重複的 If-Else 程式码

责任链模式 x 样板方法程式实作

总複习

软体设计模式精通之旅

试吃课程送 Astah UML Editor


前言

大家好,我是水球潘。

今天我们要来介绍一个 GoF 软体设计模式中的一位狠角色,责任链模式 (Chain Of Responsibility Pattern),简称 CoR。责任链模式是我最喜欢的模式之一,因为他能够允许开发者持续地往一个类别中添加新的行为,使该类别得以组合各式各样的需求。

我喜欢借由「完整的实战演练」来谈论软体设计模式,而非「过度简化的案例」。如此一来才能让大家感受到设计理论与实务上之间的紧密配合。因此,我会遵照以下步骤来介绍每一个模式:

  1. 先上一份「需求」
  2. 对着需求做「面向对象分析 (OOA)」,绘制出初版类别图
  3. 照着初版类别图实作出初版程序码
  4. 察觉程序码中的 Forces
  5. 提出我们要解决的 Problem,寻找对应的软体设计模式
  6. 套用软体设计模式来解决 Problem (Forces),绘製第二版类别图
  7. 照着第二版类别图重构出第二版程式码
  8. 软体设计模式六大元素总结

你收到了一份需求

今天我们的实战演练就是在知名社群平台 Discord 上开发一款多功能的 Discord 机器人!

你要为水球软体学院开发一个 Discord 机器人 (WaterballBot)。这个机器人支援许多功能,社群成员可以在 Discord 频道中发布讯息 (Message) 来请求某一道功能。而当机器人收到讯息指令时,就会做相对应功能的处理 (Handle)。

举例来说,如果你想要看看货币汇率,你可以在频道中发布讯息 "currency",然后学院机器人就会立刻回复你汇率资讯。

目前支援以下三者讯息指令:查看机器人有哪些讯息指令可用。

  1. "help":查看机器人有哪些讯息指令可用。
  2. "currency":查看目前货币汇率。
  3. "dcard":查看最新 Dcard(知名论坛) 的文章。

讯息指令不区分大小写,不管你是打成大写开头的 Help 或是 全大写的 HELP,机器人全都能辨认。每一个讯息指令只会对应一个功能。如果讯息无法匹配到任何功能的话,机器人就会无视这则讯息。

再来,稍微说一下 Discord 的推播机制,由于这是第三方的技术,并不是本文的重点,各位稍微有个印象就好。我们能够简单地使用 Discord API,来让机器人连线 (Connect) 且登入至 Discord 之 中。登入后就能开始侦听 (Listen) 各种事件 (Event),而我们主要想侦听的事件是  MessageCreateEvent 也就是新讯息事件。每当有人在某频道中传讯息时,Discord 会通知机器人说哪一个文字频道 (Message Channel) 有了一则新讯息 (Message)。

满实用又满有挑战性的,对吧。
走吧!先进行面向对象分析。

面向对象分析 (OOA)

好,这就是我们分析出来的初版类别图了,灰色区块的部分为第三方的 Discord API 中的类别。我们先专注在学院领域模型中的 WaterballBot 类别:当呼叫 WaterballBot 的 connect operation 时,WaterballBot 会透过 Discord API 连线和登入,之后 WaterballBot 会向 Discord API 侦听MessageCreateEvent。每一次有新讯息 (Message) 时,Discord 会推播新讯息给 WaterballBot 并告知此讯息是来源自哪一个文字频道 (MessageChannel),此时 WaterballBot 就会处理 (handle) 这则讯息,讯息处理方法 (handle 方法) 的行为如同粉红色便条纸所示;主要有三种不同的讯息指令,各对应到不同的处理。

接着,我们来实作初版的程式码~

初版程式实作

WaterballBot 类别的实作分成两部分,第一部分是第三方套件的使用细节:connect 方法中撰写着我们如何透过 Discord API 让机器人连线、登入和侦听新讯息的事件:

public class WaterballBot {
    // 透過 Discord API 讓機器人連線、登入和偵聽新訊息的事件
    public void connect() throws IOException {
        String token = getDiscordToken();
        DiscordClient client = DiscordClient.create(token);
        GatewayDiscordClient gateway = client.login().block();

        gateway.on(MessageEvent.class).subscribe(e -> {
            if (e instanceof MessageCreateEvent) {
                MessageCreateEvent mce = (MessageCreateEvent) e;
                Message message = mce.getMessage();
                MessageChannel channel = message.getChannel().block();
                handle(message, channel);
            }
        });
        gateway.onDisconnect().block();
    }

		private static String getDiscordToken() throws IOException {
        try (InputStream in = currentThread().getContextClassLoader().getResourceAsStream("token.properties")) {
            Properties properties = new Properties();
            properties.load(in);
            return String.valueOf(properties.get("TOKEN"));
        }
    }
		...

这部分大略阅读过去就行,直接来看第二部分今天的重点,机器人该如何做 message handling:

    public void handle(Message message, MessageChannel channel) {
        if ("help".equalsIgnoreCase(message.getContent())) {
            channel.createMessage("▋ HELP ▋").block();
            channel.createMessage("Commands: dcard, currency").block();
        } else if ("dcard".equalsIgnoreCase(message.getContent())) {
            String dcardBody = crawlDcardBody();
            channel.createMessage("▋ DCARD ▋").block();
            channel.createMessage(dcardBody).block();
        } else if ("currency".equalsIgnoreCase(message.getContent())) {
            String currencyBody = crawlCurrencyBody();
            channel.createMessage("▋ CURRENCY ▋").block();
            channel.createMessage(currencyBody).block();
        }
    }

    private String crawlDcardBody() { /* 實作 Dcard 爬蟲 */ }
		private String crawlCurrencyBody() { /* 實作匯率資訊爬蟲 */}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值