原理或定義
把抽象部分和它的实现部分分离开来,让两者可独立变化。这里的抽象部分指的是一个概念层次上的东西,它的实现部分指的是实现这个东西的(功能)部分,分离就把实现部分从它要实现的抽象部分独立出来,自我封装成对象。
结构
抽象化(Abstraction)角色:抽象化给出的定义,并保存一个对实现化对象的引用。
修正抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。
具体实现化(Concrete Implementor)角色:这个角色给出实现接口的具体实现;
類圖
案例与代码
本模式以遥控器项目来介绍
极简设计方案:
public interface TvControl {
public void Onoff();
public void nextChannel();
public void preChannel();
}
class LGTvControl extends LGControl implements TvControl{
private static int ch=0;
private static boolean ison=false;
public void Onoff()
{
if(ison)
{
ison=false;
super.Off();
}else{
ison=true;
super.On();
}
}
public void nextChannel()
{
ch++;
super.setChannel(ch);
}
public void preChannel()
{
ch--;
if(ch<0)
{
ch=200;
}
super.setChannel(ch);
}
}
public class SonyTvControl extends SonyControl implements TvControl{
private static int ch=0;
private static boolean ison=false;
public void Onoff()
{
if(ison)
{
ison=false;
super.Off();
}else{
ison=true;
super.On();
}
}
public void nextChannel()
{
ch++;
super.setChannel(ch);
}
public void preChannel()
{
ch--;
if(ch<0)
{
ch=200;
}
super.setChannel(ch);
}
}
public class MainTest {
public static void main(String[] args) {
LGTvControl mLGTvControl=new LGTvControl();
SonyTvControl mSonyTvControl=new SonyTvControl();
mLGTvControl.Onoff();
mLGTvControl.nextChannel();
mLGTvControl.nextChannel();
mLGTvControl.preChannel();
mLGTvControl.Onoff();
mSonyTvControl.Onoff();
mSonyTvControl.preChannel();
mSonyTvControl.preChannel();
mSonyTvControl.preChannel();
mSonyTvControl.Onoff();
}
}
新需求:电视机厂家,遥控器新设计
这样的设计方式每增加被遥控设备和遥控器改版都会带来开发的不便。
桥接模式的设计方案:
类图:
实现化(Implementor)角色:
public interface Control {
public void On();
public void Off();
public void setChannel(int ch);
public void setVolume(int vol);
}
public class LGControl implements Control {
@Override
public void On() {
// TODO Auto-generated method stub
System.out.println("**Open LG TV**");
}
@Override
public void Off() {
// TODO Auto-generated method stub
System.out.println("**Off LG TV**");
}
@Override
public void setChannel(int ch) {
// TODO Auto-generated method stub
System.out.println("**The LG TV Channel is setted "+ch+"**");
}
@Override
public void setVolume(int vol) {
// TODO Auto-generated method stub
System.out.println("**The LG TV Volume is setted "+vol+"**");
}
}
public class SharpControl implements Control {
@Override
public void On() {
// TODO Auto-generated method stub
System.out.println("***Open Sharp TV***");
}
@Override
public void Off() {
// TODO Auto-generated method stub
System.out.println("***Off Sharp TV***");
}
@Override
public void setChannel(int ch) {
// TODO Auto-generated method stub
System.out.println("***The Sharp TV Channel is setted "+ch+"***");
}
@Override
public void setVolume(int vol) {
// TODO Auto-generated method stub
System.out.println("***The Sharp TV Volume is setted "+vol+"***");
}
}
public class SonyControl implements Control {
@Override
public void On() {
// TODO Auto-generated method stub
System.out.println("*Open Sony TV*");
}
@Override
public void Off() {
// TODO Auto-generated method stub
System.out.println("*Off Sony TV*");
}
@Override
public void setChannel(int ch) {
// TODO Auto-generated method stub
System.out.println("*The Sony TV Channel is setted "+ch+"*");
}
@Override
public void setVolume(int vol) {
// TODO Auto-generated method stub
System.out.println("*The Sony TV Volume is setted "+vol+"*");
}
}
抽象化(Abstraction)角色 :
public abstract class TvControlabs {
Control mControl=null;
public TvControlabs(Control mControl)
{
this.mControl=mControl;
}
public abstract void Onoff();
public abstract void nextChannel();
public abstract void preChannel();
}
修正抽象化(Refined Abstraction)角色 :
public class TvControl extends TvControlabs {
private int ch=0;
private boolean ison=false;
public TvControl(Control mControl)
{
super(mControl);
}
@Override
public void Onoff() {
// TODO Auto-generated method stub
if(ison)
{
ison=false;
mControl.Off();
}else{
ison=true;
mControl.On();
}
}
@Override
public void nextChannel() {
// TODO Auto-generated method stub
ch++;
mControl.setChannel(ch);
}
@Override
public void preChannel() {
// TODO Auto-generated method stub
ch--;
if(ch<0)
{
ch=200;
}
mControl.setChannel(ch);
}
}
public class newTvControl extends TvControlabs {
private int ch=0;
private boolean ison=false;
private int prech=0;
public newTvControl(Control mControl) {
super(mControl);
// TODO Auto-generated constructor stub
}
@Override
public void Onoff() {
// TODO Auto-generated method stub
if(ison)
{
ison=false;
mControl.Off();
}else{
ison=true;
mControl.On();
}
}
@Override
public void nextChannel() {
// TODO Auto-generated method stub
prech=ch;
ch++;
mControl.setChannel(ch);
}
@Override
public void preChannel() {
// TODO Auto-generated method stub
prech=ch;
ch--;
if(ch<0)
{
ch=200;
}
mControl.setChannel(ch);
}
public void setChannel(int nch)
{
prech=ch;
ch=nch;
mControl.setChannel(ch);
}
public void Back()
{
mControl.setChannel(prech);
}
}
测试类:
public class MainTest {
public static void main(String[] args) {
TvControl mLGTvControl;
TvControl mSonyTvControl;
mSonyTvControl=new TvControl(new SonyControl());
mLGTvControl=new TvControl(new LGControl());
mLGTvControl.Onoff();
mLGTvControl.nextChannel();
mLGTvControl.nextChannel();
mLGTvControl.preChannel();
mLGTvControl.Onoff();
mSonyTvControl.Onoff();
mSonyTvControl.preChannel();
mSonyTvControl.preChannel();
mSonyTvControl.preChannel();
mSonyTvControl.Onoff();
newTvControl mSharpTvControl;
mSharpTvControl=new newTvControl(new SharpControl());
mSharpTvControl.Onoff();
mSharpTvControl.nextChannel();
mSharpTvControl.setChannel(9);
mSharpTvControl.setChannel(28);
mSharpTvControl.Back();
mSharpTvControl.Onoff();
}
}
将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。
系统有多维角度分类时,而每一种分类又有可能变化,考虑使用桥接模式
桥接的目的是分离抽象与实现,使抽象和实现可以独立变化。
使用場景
1、如果你不希望在抽象和实现部分采用固定的绑定关系,可以采用桥接模式,来把抽象和实现部分分开,然后在程序运行期间来动态的设置抽象部分需要用到的具体的实现,还可以动态切换具体的实现。
2、如果出现抽象部分和实现部分都应该可以扩展的情况,可以采用桥接模式,让抽象部分和实现部分可以独立的变化,从而可以灵活的进行单独扩展,而不是搅在一起,扩展一边会影响到另一边。
3、如果希望实现部分的修改,不会对客户产生影响,可以采用桥接模式,客户是面向抽象的接口在运行,实现部分的修改,可以独立于抽象部分,也就不会对客户产生影响了,也可以说对客户是透明的。
4、如果采用继承的实现方案,会导致产生很多子类,对于这种情况,可以考虑采用桥接模式,分析功能变化的原因,看看是否能分离成不同的纬度,然后通过桥接模式来分离它们,从而减少子类的数目
優缺點
主要优点有:
1. 分离抽象部分和实现部分。
2. 更好的扩展性