您的位置:首页 > 编程语言 > Java开发

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

2015-07-28 16:46 357 查看
跟着《软件秘笈---设计模式那点事》学习

预热:

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

定义:

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

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

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

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

角色:

开关,电灯,电线

类图:



实例:

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

/*
* 开关基类(预告:子类是电灯)
* */
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类。

参考资料:

《软件秘笈---设计模式那点事》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: