初识设计模式——桥接模式

学习笔记

意图:把对象的实体部分与抽象部分分离开来,分开进行组合封装,使它们可以分别的变化。

主要解决:主要解决的问题是存在多种变化的可能性,而各种的可能性不能通过简单的扩展就可以完成,会造成后续的类的数量爆炸式增多的问题。

实现方式:将一个对象进行分割,将实体部分与抽象部分隔离出来,分别封装。在调用的时候,通过类的多态特性进行聚合调用。

个人理解

合成/聚合复用原则(CARP)中提到,尽量使用合成/聚合,尽量不要使用类的继承。目前开发中主流的观点是高内聚,低耦合,而对象的继承关系本身就是高耦合性的代表,当父类或接口中出现了任何变化,势必会导致子类发生变化。

桥接模式通过将实体与抽象分离的方法,把后期可能会发生改变的抽象功能分离出去,使得实体类不会频繁的发生改变,大大降低了类与类之间的耦合性。这里说明一下,当初开始理解的时候有疑问,如果将抽象功能分离开来,不是将会增加实体类、抽象类两个类直接的耦合性吗,为什么会说降低耦合性呢。原因就在于类的多态特性。我们可以通过参数传递的方式连接两个类,这样就在能保证未来可变的前提下,降低了耦合性。

主要的实现方式是将一个对象分为两个部分,一个部分为实体类(需要对外部提供功能的部分),一个部分为抽象类(对象中存在,但外部不是必须了解知道的部分)。

案例分析

某公司存在三款产品,为了便于统一管理,现需要做一套完整的产品管理统计平台,主要用于多维度统计每个产品的使用情况,目前主要统计每个产品的调用量、每个产品的有效调用等等数据。每个产品的统计均通过不同的接口(各项目组的接口)进行返回。

第一种方案:使用模板模式,创建一个模板抽象类,将可以进行统一处理的方法放在模板抽象类中,将产品中不同的方法放在每个具体的产品类中。问题出现在当后期频繁增加产品、统计方案时,需要维护的代码量大大增加(不仅需要修改抽象模板类,还需要修改每个产品中的方法,而且修改的代码量也会非常多)。

第二种方案:将产品与统计方案割离开,对产品封装一套体系,统计方案为一套体系。现在的问题是,这两套体系中,那个为抽象类,那个为具体类。这个需要分析一下,我们最终需要看到的是什么?是产品吗,显然不是,我们需要看到的是统计数据,所以这里应该以产品作为抽象类体系,统计作为具体类体系。

案例代码

产品体系

<?php
//桥接模式
//产品接口
interface Product
{
    public function getProductId();
    public function getField();
    public function getData();
}

//产品A
class A implements Product {
    public function getProductId()
    {
        return 101;
    }
    public function getField()
    {
        return ['Aa', 'Ab', 'Ac'];
    }
    public function getData()
    {
        $data = [];
        //统计的数据
        return $data;
    }
}

//产品B
class B implements Product {
    public function getProductId()
    {
        return 102;
    }
    public function getField()
    {
        return ['Ba', 'Bb', 'Bc'];
    }
    public function getData()
    {
        $data = [];
        //统计的数据
        return $data;
    }
}
//产品C
class C implements Product {
    public function getProductId()
    {
        return 103;
    }
    public function getField()
    {
        return ['Ca', 'Cb', 'Cc'];
    }
    public function getData()
    {
        $data = [];
        //统计的数据
        return $data;
    }
}

统计体系:

<?php
//统计体系
abstract class Statistics{
    private $product;
    public function __construct(Product $product)
    {
        $this->product = $product;
    }
    protected function getProductData()
    {
        return $this->product->getData();
    }
    abstract public function list_data();
    abstract public function charts();
}
//折线走势统计图
class ZheXian extends Statistics {
    public function list_data()
    {
        $data = $this->getProductData();
        //数据的处理
        return [];
    }
    public function charts()
    {
        $data = $this->getProductData();
        //数据的处理
        return '返回的折线图';
    }
}
//并状图
class Bing extends Statistics {
    public function list_data()
    {
        $data = $this->getProductData();
        //数据的处理
        return [];
    }
    public function charts()
    {
        $data = $this->getProductData();
        //数据的处理
        return '饼状图';
    }
}

客户端:

//客户端
//获取A的折线统计图
$a = new A();
$zhexian = new ZheXian($a);

//获取B的饼状图
$b = new B();
$bing = new Bing($b);

//C的统计图两个都要
$c = new C();
$c_zhexian = new ZheXian($c);
$c_bing = new Bing($c);

如果需要增加一种统计图,我们只需要增加一个统计图的具体类即可,如果需要增加一款产品,同样的我们只需要增加一个产品类即可,不需要修改过多的类。说白了,无非就是实现了统计与产品的解耦

UML图

下一篇

初始设计模式——命令模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值