一、桥接模式
将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变
二、示例
电视机遥控器项目:假设电视机的遥控器都是统一的开关、加、减的3个按钮,则不同品牌的电视机需要对这3个按钮进行各自的功能实现
使用传统的面向对象模式结合超类的接口实现
1.定义遥控器内部用到的统一方法接口
/**
* 桥接模式,将遥控器所有需要用到的方法进行统一定义
*/
public interface Control {
public void On();
public void Off();
public void setChannel(int ch);
public void setVolume(int vol);
}
2.不同的遥控器厂家对接口进行实现
/**
* 桥接模式,LG遥控器对遥控器统一方法的实现
*/
public class LGControl implements Control {
@Override
public void On() {
System.out.println("**Open LG TV**");
}
@Override
public void Off() {
System.out.println("**Off LG TV**");
}
@Override
public void setChannel(int ch) {
System.out.println("**The LG TV Channel is setted " + ch + "**");
}
@Override
public void setVolume(int vol) {
System.out.println("**The LG TV Volume is setted " + vol + "**");
}
}
/**
* 桥接模式,Sony遥控器对遥控器统一方法的实现
*/
public class SonyControl implements Control {
@Override
public void On() {
System.out.println("*Open Sony TV*");
}
@Override
public void Off() {
System.out.println("*Off Sony TV*");
}
@Override
public void setChannel(int ch) {
System.out.println("*The Sony TV Channel is setted " + ch + "*");
}
@Override
public void setVolume(int vol) {
System.out.println("*The Sony TV Volume is setted " + vol + "*");
}
}
3.定义统一的电视遥控器界面上的接口
/**
* 面向对象模式,所有遥控器统一的界面,界面上定义3个统一的按钮
*/
public interface TvControl {
public void Onoff();
public void nextChannel();
public void preChannel();
}
4.不同的电视机厂家对遥控器界面按钮的功能实现
/**
* 面向对象模式,定义厂家的遥控器对象,实现厂家制定的遥控器方法
*/
public 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);
}
}
5.对外调用输出
/**
* 传统面向对象的模式
*/
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();
}
}
三、桥接模式改进
如果现在要新增电视机厂家或新增遥控器种类,则极不利于拓展。
观察可以发现虽然不同厂家的电视遥控器品牌不同,但是内部功能的调用是一样的。如果随着品牌的增加,则需要给每个品牌制定一款遥控器实现的对象。因此可以将遥控器的调用模式抽象出来统一调用,如果有新的调用方法,也同理进行抽象实现
1.定义统一的抽象类
/**
* 桥接模式,桥接的抽象类,定义基本的抽象方法可桥接对象
*/
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();
}
2.定义相同实现方式的桥接对象,对抽象类的方法进行实现
/**
* 桥接模式,基础遥控器的方法实现
*/
public class TvControl extends TvControlabs {
private int ch = 0;
private boolean ison = false;
public TvControl(Control mControl) {
super(mControl);
}
@Override
public void Onoff() {
if (ison) {
ison = false;
mControl.Off();
} else {
ison = true;
mControl.On();
}
}
@Override
public void nextChannel() {
ch++;
mControl.setChannel(ch);
}
@Override
public void preChannel() {
ch--;
if (ch < 0) {
ch = 200;
}
mControl.setChannel(ch);
}
}
3.若有新类型的统一的遥控器出现,直接在基础类上进行拓展实现
/**
* 桥接模式,新电视机类型,实现基础抽象方法,以及新型的遥控器的方法
*/
public class newTvControl extends TvControlabs {
private int ch = 0;
private boolean ison = false;
private int prech = 0;
public newTvControl(Control mControl) {
super(mControl);
}
@Override
public void Onoff() {
if (ison) {
ison = false;
mControl.Off();
} else {
ison = true;
mControl.On();
}
}
@Override
public void nextChannel() {
prech = ch;
ch++;
mControl.setChannel(ch);
}
@Override
public void preChannel() {
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);
}
}
4.定义遥控器时直接传入需要用到的控制器种类即可
/**
* 桥接模式
* 通过抽象类定义需要用到的方法抽象以及拓展方法的实现
* 接口定义底层有的所有功能方法
* 不同的对象实现不同的接口方法
* 将实现接口的对象引入到抽象类中
*/
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();
}
}
四、总结
- 系统有多维角度分类时,而每一种分类又有可能变化,考虑使用桥接模式
- 桥接的目的是分离抽象与实现,使抽象和实现可以独立变化。
- 桥接的目的是让底层实现和上层接口可以分别演化,从而提高移植性
- 桥接模式是往往是为了利用已有的方法或类
- 桥接模式强调接口对象仅提供基本操作
Java设计模式所有示例代码,持续更新中