PHP设计模式之桥接模式

桥接模式的定义是 “将抽象和实现解耦,让它们可以独立变化”。一个类存在两个(或多个)独立变化的维度,通过组合的方式可以让这两个(或多个)维度可以独立进行扩展。简单地说,桥接模式主要是处理二维模型的问题。

这里举一个API接口监控告警的例子:根据不同的告警规则,触发不同渠道的不同紧急程度的告警。

  • 告警支持多种通知渠道,包括:邮件、微信、语音电话。
  • 通知的紧急程度有多种类型,包括:严重、紧急、普通。

也就是说,这是一个二维的模型,可能会有下面的组合:

  • 严重程度发邮件
  • 严重程度发微信消息
  • 严重程度打语音电话
  • 紧急程度发邮件
  • 紧急程度发微信消息
  • 紧急程度打语音电话
  • 普通程度发邮件
  • 普通程度发微信消息
  • 普通程度打语音电话

下面用PHP的代码实现上面的业务场景。

<?php

/**
 * 抽象的信息类
 */
abstract class Msg {
    public $bridge;

    public function __construct(MessageType $bridge) {
        $this->bridge = $bridge;
    }

    abstract public function msg($content);

    public function send($to, $content) {
        $content = $this->msg($content);
        $this->bridge->send($to, $content);
    }
}

/**
 * 按照 紧急程度 划分三个类
 */
//严重程度
class Severe extends Msg {
    public function msg($content) {
        return '[严重] ' . $content;
    }
}

//紧急程度
class Urgency extends Msg {
    public function msg($content) {
        return '[紧急] ' . $content;
    }
}

//普通程度
class Normal extends Msg {
    public function msg($content) {
        return '[普通] ' . $content;
    }
}

/**
 * 按照 告警类型 划分三个类
 */
interface MessageType {
    function send($to, $content);
}

//发送邮件
class Email implements MessageType {
    public function send($user, $content) {
        echo "[发邮件] 给{$user}: {$content}" . PHP_EOL;
    }
}

//发送微信
class Weixin implements MessageType {
    public function send($user, $content) {
        echo "[发微信消息] 给{$user}: {$content}" . PHP_EOL;
    }
}

//打电话
class Phone implements MessageType {
    public function send($user, $content) {
        echo "[打语音电话] 给{$user}: {$content}" . PHP_EOL;
    }
}

//根据业务需求, 客户端任意组合调用
//严重程度发邮件
$client = new Severe(new Email());
$client->send('张三', '服务器异常了1'); //[发邮件] 给张三: [严重] 服务器异常了1

//严重程度发微信消息
$client = new Severe(new Weixin());
$client->send('张四', '服务器异常了2'); //[发微信消息] 给张四: [严重] 服务器异常了2

//严重程度打语音电话
$client = new Severe(new Phone());
$client->send('张五', '服务器异常了3'); //[打语音电话] 给张五: [严重] 服务器异常了3

//紧急程度发邮件
$client = new Urgency(new Email());
$client->send('李三', '刚才接口响应超时了1'); //[发邮件] 给李三: [紧急] 刚才接口响应超时了1

//紧急程度发微信消息
$client = new Urgency(new Weixin());
$client->send('李四', '刚才接口响应超时了2'); //[发微信消息] 给李四: [紧急] 刚才接口响应超时了2

//紧急程度打语音电话
$client = new Urgency(new Phone());
$client->send('李五', '刚才接口响应超时了3'); //[打语音电话] 给李五: [紧急] 刚才接口响应超时了3

//普通程度发邮件
$client = new Normal(new Email());
$client->send('王三', '记得下班打卡1'); //[发邮件] 给王三: [普通] 记得下班打卡1

//普通程度发微信消息
$client = new Normal(new Weixin());
$client->send('王四', '记得下班打卡2'); //[发微信消息] 给王四: [普通] 记得下班打卡2

//普通程度打语音电话
$client = new Normal(new Phone());
$client->send('王五', '记得下班打卡3'); //[打语音电话] 给王五: [普通] 记得下班打卡3

从上面的代码中可以看出,桥接模式主要针对 二维模型。这种组合式的问题常规方法需要A*B种组合,而桥接模式只需要A+B种组合,维度越多,桥接模式越有优势。

如果使用传统方法,可以用下面的代码表示:

function SevereEmail($user, $content) {
    echo "[发邮件] 给{$user}: [严重] {$content}";
}

function SevereWeixin($user, $content) {
    echo "[发微信消息] 给{$user}: [严重] {$content}";
}

function SeverePhone($user, $content) {
    echo "[打语音电话] 给{$user}: [严重] {$content}";
}

function UrgencyEmail($user, $content) {
    echo "[发邮件] 给{$user}: [紧急] {$content}";
}

function UrgencyWeixin($user, $content) {
    echo "[发微信消息] 给{$user}: [紧急] {$content}";
}

function UrgencyPhone($user, $content) {
    echo "[打语音电话] 给{$user}: [紧急] {$content}";
}

function NormalEmail($user, $content) {
    echo "[发邮件] 给{$user}: [普通] {$content}";
}

function NormalWeixin($user, $content) {
    echo "[发微信消息] 给{$user}: [普通] {$content}";
}

function NormalPhone($user, $content) {
    echo "[打语音电话] 给{$user}: [普通] {$content}";
}

假设现在有5个紧急程度,告警消息的种类有6种,如果使用桥接模式只需要定义 5+6=11个类,而使用传统的方法则需要5*6=30个类(或者方法)。

因此,实际开发中如果需要表示二维(或者更多维度)模型,并且每个维度的内容越多,就可以使用桥接模式。但是如果维度很少,或者每个维度的内容不多,则可以选择使用传统的模式。

源代码:https://gitee.com/rxbook/php_design_pattern/blob/master/code12_bridge.php

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

rxbook

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

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

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

打赏作者

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

抵扣说明:

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

余额充值