在面向对象设计的时候,我们一般会根据需要,设计不同的类。但是如果两个类需要类似的功能的时候,我们就会遇到问题,到底重用还是重写。
更复杂的是,如果一些功能需要临时转换就麻烦了,比如星际里面的虫族,地面部队可以钻到地下,然后隐形。
但是小狗在地下不能动,而地刺可以攻击。尽管可以设计不同的类,但问题是玩家可以看到自己的部队埋在地下(一个洞),而敌人看不到。
这涉及功能的切换,而且星际里面有很多探测隐形的东西,这样就更频繁了。
待解决的问题:我们要临时切换一些功能的实现方式,而且在此基础上不同的调用类又有所不同。
思路:将钻地区分两种实现,不同的部队类在它的基础上进一步扩展。
桥接(Bridge)模式示例:
<?php
//虫族的基础类
class Zerg
{
//实现钻地的基本对象
public $imp;
//负责切换钻地基本对象的方法
public function setImp($imp)
{
$this->imp = $imp;
}
//部队的钻地方法,可以扩展基本对象的钻地
public function underground()
{
$this->imp->underground();
}
}
//小狗的类
class Zergling extends Zerg
{
//调用基本的钻地方法,然后实现扩展,这里简单的echo
public function underground()
{
parent::underground();
echo '小狗不能动<br>';
}
}
//地刺的类
class Lurker extends Zerg
{
//调用基本的钻地方法,然后实现扩展,这里简单的echo
public function underground()
{
parent::underground();
echo '地刺能够进行攻击<br>';
}
}
//钻地的基本接口
interface Implementor
{
//基本的钻地方法
public function underground();
}
//隐形钻地的基本类
class InvisibleImp implements Implementor
{
//基本的钻地方法
public function underground()
{
echo '隐形了,什么也看不到<br>';
}
}
//不隐形钻地的基本类,比如玩家自己看到的或被探测到的
class VisibleImp implements Implementor
{
//基本的钻地方法
public function underground()
{
echo '地上一个洞<br>';
}
}
//造一个小狗
$z1 = new Zergling();
//玩家把它埋入前沿阵地,假设此时有敌人经过,代码进行切换
$z1->setImp(new InvisibleImp());
//敌人看不到小狗,但是小狗也不能进攻
$z1->underground();
//造一个地刺
$l1 = new Lurker();
//玩家把它埋入前沿阵地,假设此时有敌人经过,代码进行切换
$l1->setImp(new InvisibleImp());
//敌人看不到地刺,但是地刺能攻击敌人
$l1->underground();
//敌人急了,马上飞过来一个科技球,代码进行切换
$l1->setImp(new VisibleImp());
//敌人看到地刺了,地刺继续攻击敌人
$l1->underground();
?>
用途总结:桥接模式可以将基本的实现和具体的调用类分开,调用类可以扩展更复杂的实现。
实现总结:需要一些基本执行类,实现基本的方法,比如上面的两个钻地类。同时我们可以设计多个不同的扩展调用类,将基本的功能扩展,比如地刺和小狗就进一步实现了不同的在地下的行为。