又称:Bridge。桥接是一种结构型设计模式,可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构,从而能在开发时分别使用。
前面说的:抽象? 实现? 听上去很高大尚? 假如有一个 台式电脑机箱(Case) 类,从它能扩展出三个子 类: 普通机箱(DefaultCase) 、 海景房机箱(SeascapeCase) 、 异形机箱(AlienCase)。然后我们希望对这样的类层次结构进行扩展以使其包含颜色, 所以打算创建名为 黑色(Black)、白色(White) 、 透明(Transparent) 的颜色子类。 但是, 由于已有三个子类,所以总共需要创建 九个 类才能覆盖所有组合, 例如:黑色异形机箱(BlackCase) 和 **白色异形机箱(WhiteCase)**。
在层次结构中新增形状和颜色将导致代码复杂程度指数增长。例如添加 紫色,你需要新增 三个子类,也就是每种颜色 一个; 此后新增一种新颜色需要新增 三个子类, 即每种形状 一个。一直这么下去,情况会越来越难受。
通过将 继承改为组合 的方式来解决这个问题。 具体来说,就是 抽取其中一个维度 并使之成为 独立的类层次,这样就可以在初始类中引用这个 新层次的对象,从而使得一个类不必拥有所有的状态和行为。
可以将颜色相关的代码抽取到拥有 黑色 、 白色 、 透明 三个子类的颜色类中,然后在 机箱 类中添加一个 指向某一颜色对象的引用成员变量。 机箱类可以将所 有与颜色相关的工作委派给连入的颜色对象。 这样的引用就 成为了 机箱 和 颜色 之间的桥梁。
CaseAbstract:抽象类 在本示例中指 机箱; DefaultCase、SeascapeCase、AlienCase:扩充抽象类 在本示例中指 普通机箱、海景房机箱、异形机箱; ColorInterface:实现类 在本示例中指 颜色; Black、White、Transparent:具体实现类 在本示例中指黑色、白色、透明;
abstract class CaseAbstract
{
/**
* 颜色
* @var \cxbdasheng\DesignPatterns\Bridge\ColorInterface
*/
protected $color;
/**
* 运行机箱
* @return mixed
* @author chendashengpc
*/
abstract public function run();
/**
* 默认颜色
* @param \cxbdasheng\DesignPatterns\Bridge\ColorInterface $color
*/
public function __construct(ColorInterface $color)
{
$this->color = $color;
}
}
interface ColorInterface
{
public function getInfo();
}
/**
*
* 普通机箱
*/
class DefaultCase extends CaseAbstract
{
public function run()
{
return $this->color->getInfo() . '普通机箱';
}
}
/**
*
* 海景房机箱
*/
class SeascapeCase extends CaseAbstract
{
public function run()
{
return $this->color->getInfo() . '海景房机箱';
}
}
/**
*
* 异形机箱
*/
class AlienCase extends CaseAbstract
{
public function run()
{
return $this->color->getInfo() . '异形机箱';
}
}
class Black implements ColorInterface
{
public function getInfo()
{
return '黑色';
}
}
class White implements ColorInterface
{
public function getInfo()
{
return '白色';
}
}
class Transparent implements ColorInterface
{
public function getInfo()
{
return '透明';
}
}
$black = new Black();
$white = new White();
$transparent = new Transparent();
$blackAlienCase = new AlienCase($black);
echo $blackAlienCase->run() . PHP_EOL;
$whiteAlienCase = new AlienCase($white);
echo $whiteAlienCase->run() . PHP_EOL;
$transparentAlienCase = new AlienCase($transparent);
echo $transparentAlienCase->run() . PHP_EOL;
echo PHP_EOL;
$blackSeascapeCase = new SeascapeCase($black);
echo $blackSeascapeCase->run() . PHP_EOL;
$whiteSeascapeCase = new SeascapeCase($white);
echo $whiteSeascapeCase->run() . PHP_EOL;
$transparentSeascapeCase = new SeascapeCase($transparent);
echo $transparentSeascapeCase->run() . PHP_EOL;
输出
黑色异形机箱
白色异形机箱
透明异形机箱
黑色海景房机箱
白色海景房机箱
透明海景房机箱
黑色普通机箱
白色普通机箱
透明普通机箱
从代码可以发现跟上篇文章的 适配器模式 有点像,都是聚合让两个类配合工作,但是适配器是为了让已有的两个类互相兼容,而桥接模式则是为了让抽象和实现解耦,在减少创建类的同时还可以方便组合功能。