重学java23种设计模式(7)桥接模式

跟着《软件秘笈---设计模式那点事》学习


预热:

一个各种开关,各种灯泡,中间一种电线的故事

定义:

将抽象与实现分离,使他们都可以独立变化。

在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?这就要使用桥接模式,桥接模式使得软件系统能够轻松沿着多个方象进行变化,而又不引入额外的复杂度。

桥接模式的用意是,将抽象化与实现化解耦,使得二者可以独立地变化,关键词,抽象化,实现化,解耦。

很显然,将继承改为聚合就是上面说的抽象和实现之间的解耦,从而使两者可以独立变化。


角色:

开关,电灯,电线


类图:


实例:

首先用继承的方式实现电灯与开关,也就是电灯继承开关。

/*
 * 开关基类(预告:子类是电灯)
 * */
public abstract class AbsSwitch {
	// 打开开关
	public abstract void turnOn();
	// 照明
	public abstract void light();
	// 关闭开关
	public abstract void turnOff();
	// 开灯照明
	public final void makeLight(){
		this.turnOn();
		this.light();
		this.turnOff();
	}
}
/*
 * 白炽灯
 * */
public class IncandescentLight extends AbsSwitch {

	@Override
	public void turnOn() {
		System.out.println("白炽灯打开了。。。。。");
	}

	@Override
	public void light() {
		System.out.println("白炽灯照明");
	}

	@Override
	public void turnOff() {
		System.out.println("白炽灯关闭");
	}

}
/*
 * 水晶灯
 * */
public class CrystalLight extends AbsSwitch {

	@Override
	public void turnOn() {
		System.out.println("水晶灯打开了。。。。。");
	}

	@Override
	public void light() {
		System.out.println("水晶灯照明");
	}

	@Override
	public void turnOff() {
		System.out.println("水晶灯关闭");
	}

	/*
	 * 使用遥控开关控制开灯和颜色
	 */
	public final void makeRemoteLight(int openColor) {
		// 打开开关接同电流
		this.turnOn();
		// 照明
		this.light();
		String color = "";
		switch (openColor) {
		case 1:
			color = "暖色";
			break;
		case 2:
			color = "蓝色";
			break;
		case 3:
			color = "红色";
			break;
		default:
			color = "白色";
			break;
		}
		System.out.println("现在是:" +color + "。。。。。" );
		//断开开关关闭电流
		this.turnOff();
	}
}

public class Client {

	public static void main(String[] args) {
		//白炽灯实例
		AbsSwitch light = new IncandescentLight();
		//水晶灯实例
		CrystalLight light2 = new CrystalLight();
		System.out.println("-----一般开关-----");
		light.makeLight();
		System.out.println("\n-----遥控开关-----");
		light2.makeRemoteLight(1);
	}

}

很显然,水晶灯的开关无法控制白炽灯,白炽灯的开关无法控制水晶灯。

看看桥接模式的开关

电灯有自己的接口,开关有自己的基类,开关基类持有电灯接口,并通过构造方法注入。

package com.demo.bridge.lights;

/**
 * 电灯接口
 */
public interface ILight {
	// 接通电流
	public void electricConnected();
	// 照明
	public void light();
	// 断开电流
	public void electricClosed();
}

/*
 * 开关基类
 * */
public class BaseSwitch {
	//使用组合,设置ILight为内部私有属性,此为桥梁
	protected ILight light;
	//用构造方法将外部light注入进来
	public BaseSwitch(ILight light) {
		this.light = light;
	}
	//开关灯方法
	public final void makeLight(){
		this.light.electricConnected();
		this.light.light();
		this.light.electricClosed();
	}
}

下面是白炽灯和水晶灯。

public class IncandescentLight implements ILight {

	@Override
	public void electricConnected() {
		System.out.println("白炽灯打开了。。。。。");
	}

	@Override
	public void light() {
		System.out.println("白炽灯照明");
	}

	@Override
	public void electricClosed() {
		System.out.println("白炽灯关闭");
	}

}

/*
 * 水晶灯
 * */
public class CrystalLight implements ILight {

	@Override
	public void electricConnected() {
		System.out.println("水晶灯打开了。。。。。");
	}

	@Override
	public void light() {
		System.out.println("水晶灯照明");
	}

	@Override
	public void electricClosed() {
		System.out.println("水晶灯关闭");
	}
}

import com.demo.bridge.lights.ILight;

/*
 * 水晶灯开关
 * */
public class RemoteControlSwitch extends BaseSwitch {
	//构造方法注入
	public RemoteControlSwitch(ILight light) {
		super(light);
	}

	/*
	 * 使用遥控开关控制开灯和颜色
	 */
	public final void makeRemoteLight(int openColor) {
		// 打开开关接同电流
		this.light.electricConnected();
		// 照明
		this.light.light();
		String color = "";
		switch (openColor) {
		case 1:
			color = "暖色";
			break;
		case 2:
			color = "蓝色";
			break;
		case 3:
			color = "红色";
			break;
		default:
			color = "白色";
			break;
		}
		System.out.println("现在是:" +color + "。。。。。" );
		//断开开关关闭电流
		this.light.electricClosed();
	}
}

客户端:

import com.demo.bridge.lights.CrystalLight;
import com.demo.bridge.lights.ILight;
import com.demo.bridge.lights.IncandescentLight;
import com.demo.bridge.switchs.BaseSwitch;
import com.demo.bridge.switchs.RemoteControlSwitch;

public class Client4Bridge {

	public static void main(String[] args) {
		//白炽灯实例
		ILight light1= new IncandescentLight();
		//水晶灯实例
		ILight light2 = new CrystalLight();
		
		System.out.println("-----一般开关-----");
		BaseSwitch switch1 = new BaseSwitch(light1);
		switch1.makeLight();
		System.out.println("\n-----遥控开关-----");
		RemoteControlSwitch switch2 = new RemoteControlSwitch(light2);
		switch2.makeRemoteLight(1);
		System.out.println("\n-----让遥控开关开关白炽灯-----");
		RemoteControlSwitch switch3 = new RemoteControlSwitch(light1);
		switch3.makeRemoteLight(1);
	}

}


分析:

我认为软件秘籍里面这个例子很形象,电灯开关的继承关系太牵强,但又的确有可能被当做继承使用。

解决方案就是开关持有灯的引用,通过构造方法注入。


使用场合:

(1)不希望抽象类和它的实现部分之间有一个固定的绑定关系。

(2)类的抽象及实现都应该通过生成子类的方法加以扩充。

(3)对一个抽象的实现部分修改应对客户不产生影响,即客户的代码不必重新编译。


一句话总结:

所谓继承对象之间解耦,就是不用继承改用组合。


Java SDK中的原型模式:

java.utli.logging中的Handler和Formatter类。


参考资料:

《软件秘笈---设计模式那点事》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值