设计模式15-桥接模式

128 阅读4分钟

1.场景问题解决

1.1 场景描述

遥控器项目:电视厂商在电视机中预留了接口,遥控器外包给外部生产.
需要设计遥控器的功能.当前有LG电视机和sony电视机,提供各自接口,需要生产各自的遥控器.
用继承的方式,给每个电视厂商编写各自的遥控器.

1.2 OO设计

自己遥控器设置了一个接口,为不用的厂家单独设计遥控器(集成商家的接口. ). 15桥接模式-1-oo

[15桥接模式-1-oo](https://github.com/bobshute/public/blob/master/imgs/csdn/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/15%E6%A1%A5%E6%8E%A5%E6%A8%A1%E5%BC%8F-1-oo.png)
  • 基本类 Control,LGControl,SharpControl,SonyControl(电视机厂商的接口与电视内置实现)
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() {
		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+"**");
	}
}



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+"*");
	}

}




public class SharpControl implements Control {
	@Override
	public void On() {
		System.out.println("***Open Sharp TV***");
	}

	@Override
	public void Off() {
		System.out.println("***Off Sharp TV***");
	}

	@Override
	public void setChannel(int ch) {
		System.out.println("***The Sharp TV Channel is setted "+ch+"***");
	}

	@Override
	public void setVolume(int vol) {
		System.out.println("***The Sharp TV Volume is setted "+vol+"***");
	}

}
  • oo设计时的实现方式
    • TvControl,LGTvControl,SonyTvControl
    • 外包遥控器接口及实现
public interface TvControl {
	public void Onoff();
	public void  nextChannel();
	public void  preChannel();
}



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);
	}

}




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();
	}
}



1.3 需求变动

  • 新的电视机厂商
  • 遥控器也增加新功能,需要直接跳转到某频道.

1.4 带来问题

那么就要修改原遥控器,

2.用设计模式改进

2.1 分析

新增抽象类中组合使用接口.

15桥接模式-1-桥接模式

桥接模式:将实现(桥左侧上与下一起)与抽象(桥右侧上与下一起)放在两个不同的类层次中,使两个层次可以独立改变

2.2 重新设计

  • TvControlabs 新的遥控抽象类
    • TvControl 和oo设计一样的遥控板
    • newTvControl 新款遥控板
    • TestBridge 测试类

不用为每个厂商类单独设计遥控板,而是通用
新的遥控板功能模板不用修改原设计,新增新遥控板即可

public abstract class TvControlabs {

    //oo代码中的Control 
	Control mControl=null;

	public TvControlabs(Control mControl){
		this.mControl=mControl;
	}
	
	public abstract void Onoff();
	public abstract void nextChannel();
	public abstract void preChannel();

}




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);
	}
}



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);
	}
}



public class TestBridge {
	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();
		
	}
}

3.设计模式总结

3.1 定义

桥接模式:将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变

3.2 分析思路

系统有多维角度分类时,而每一种分类又有可能变化,考虑使用桥接模式
桥接的目的是分离抽象与实现,使抽象和实现可以独立变化。

3.3 与其它模式对比

  • 桥接的目的是让底层实现和上层接口可以分别演化,从而提高移植性
  • 策略的目的是将复杂的算法封装起来,从而便于替换不同的算法
  • 桥接模式是往往是为了利用已有的方法或类
  • 策略模式是为了扩展和修改,并提供动态配置
  • 桥接模式强调接口对象仅提供基本操作
  • 策略模式强调接口对象提供的是一种算法

4. 设计模式使用场景及注意

5.参考文章

内容总计于HeadFirst设计模式及相关视频