桥接模式

类图

2024061810173641.png

不使用桥接模式

抽象工厂模式中的示例代码就是没有使用桥接模式的典范。

其中涉及到的维度有:

工厂有:

工厂的数量 = 平台数量 x 表单控件的数量。如果新增 Linux 平台和 Radio 控件,则工厂数量将会是:

使用桥接模式实现产品组合

桥接模式把类的功能层次实现层次分离,以便它们独立变化。在上述示例中,如何判断什么是功能层次,什么是实现层次呢?这个需要具体问题具体分析。

经过查阅多个资料,通常会把实体作为抽象层次,另一个维度作为实现层次。换句话说,上述工厂要生产的东西是 ButtonCheckbox,则可以把表单控件作为抽象层次来看待,而操作系统作为实现层次。

<?php
 
// 实现部分
interface System
{
public function applySystem();
}
 
// 具体实现1
class Win implements System
{
public function applySystem()
{
return "Windows";
}
}
 
// 具体实现2
class Mac implements System
{
public function applySystem()
{
return "macOS";
}
}
 
// 抽象部分
abstract class FormControl
{
protected $system;
 
public function __construct(System $system)
{
$this->system = $system;
}
 
abstract public function render();
}
 
// 具体抽象1
class Button extends FormControl
{
public function render()
{
return $this->system->applySystem() . " Button";
}
}
 
// 具体抽象2
class Checkbox extends FormControl
{
public function render()
{
return $this->system->applySystem() . " Checkbox";
}
}
 
// client
$win = new Win();
$mac = new Mac();
 
$winButton = new Button($win);
$macButton = new Button($mac);
$winCheckbox = new Checkbox($win);
$macCheckbox = new Checkbox($mac);
 
echo $winButton->render() . PHP_EOL;
echo $macButton->render() . PHP_EOL;
echo $winCheckbox->render() . PHP_EOL;
echo $macCheckbox->render() . PHP_EOL;

上述代码中的 FormControl::$system 就是桥

使用桥接模式实现工厂组合

也可以提升一个维度,直接把 Factory 看作产品,即抽象部分。

生产字符串的工厂

先把问题简化,让工厂生成 string

<?php
 
// 实现部分
interface System
{
public function applySystem();
}
 
// 具体实现1
class Win implements System
{
public function applySystem()
{
return "Windows";
}
}
 
// 具体实现2
class Mac implements System
{
public function applySystem()
{
return "macOS";
}
}
 
 
// 抽象部分
abstract class GUIFactory
{
protected $system;
 
public function __construct(System $system)
{
$this->system = $system;
}
 
abstract public function createString(): string;
}
 
// 具体抽象1
class ButtonFactory extends GUIFactory
{
public function createString(): string
{
return $this->system->applySystem() . " Button";
}
}
 
// 具体抽象2
class CheckboxFactory extends GUIFactory
{
public function createString(): string
{
return $this->system->applySystem() . " Checkbox";
}
}
 
// 客户端
function client(GUIFactory $factory)
{
echo $factory->createString() . PHP_EOL;
}
 
$win = new Win();
$mac = new Mac();
 
$buttonFactory1 = new ButtonFactory($win);
$buttonFactory2 = new ButtonFactory($mac);
 
$checkboxFactory1 = new CheckboxFactory($win);
$checkboxFactory2 = new CheckboxFactory($mac);
 
client($buttonFactory1);
client($buttonFactory2);
client($checkboxFactory1);
client($checkboxFactory2);

上述代码中的 GUIFactory::$system 就是桥

生产表单控件的工厂

再把问题变复杂,让工厂生产 Button 或者 Checkbox,并把它们抽象为 FormControl

<?php
 
// 实现部分
interface System
{
public function applySystem();
}
 
// 具体实现1
class Win implements System
{
public function applySystem()
{
return "Windows ";
}
}
 
// 具体实现2
class Mac implements System
{
public function applySystem()
{
return "macOS";
}
}
 
// 额外的代码,和桥接模式无关
interface FormControl
{
public function render();
}
 
// 额外的代码,和桥接模式无关
class Button implements FormControl
{
private $system;
 
public function __construct(System $system)
{
$this->system = $system;
}
 
public function render(): string
{
return $this->system->applySystem() . "Button";
}
}
 
// 额外的代码,和桥接模式无关
class Checkbox implements FormControl
{
private $system;
 
public function __construct(System $system)
{
$this->system = $system;
}
 
public function render(): string
{
return $this->system->applySystem() . "Checkbox";
}
}
 
 
 
// 抽象部分
abstract class GUIFactory
{
protected $system;
 
public function __construct(System $system)
{
$this->system = $system;
}
 
abstract public function createFormControl(): FormControl;
}
 
// 具体抽象1
class ButtonFactory extends GUIFactory
{
public function createFormControl(): FormControl
{
return new Button($this->system);
}
}
 
// 具体抽象2
class CheckboxFactory extends GUIFactory
{
public function createFormControl(): FormControl
{
return new Checkbox($this->system);
}
}

上述代码中的 GUIFactory::$system 就是桥