一个类有可能多个变化的维度。比如坦克大战游戏,一局游戏,可以选择地图,也可以选择坦克,坦克游戏这个类有变化两个维度。坦克有很多种、地图也有很多种,并且坦克与地图的种类会逐步的添加。所以,为每种坦克与地图的组合都创建一个类,以后每当新增加一种坦克时,都需要与所有的地图组合添加新类,添加地图也是这样,这会产生类爆炸问题。
在桥接模式中,应该分别定义坦克与地图的接口并分别实现,而坦克游戏类则只包含坦克与地图的接口,具体的实现类在运行时指定。
适配置器模式侧重与转换,将不适配的接口转换成合适的接口。
装饰器模式侧重于叠加、组合同一接口的不同实现。
桥接模式侧重于组合,将代表当前类不同变化维度的接口组装在一起。
示例代码:
// 坦克接口
interface Tank {
public void fire();
}
// 具体坦克
class T34 implements Tank {
public void fire() {
System.out.println("T34:fire()");
}
}
// 另一种坦克
class T72 implements Tank {
public void fire() {
System.out.println("T72:fire()");
}
}
// 坦克工厂,封装生产坦克的逻辑
abstract class TankFactory {
public static Tank create(String type) {
if (type.equalsIgnoreCase("T34")) {
return new T34();
} else if (type.equalsIgnoreCase("T72")) {
return new T72();
} else {
return null;
}
}
}
// 地图接口
interface Map {
public void Draw();
public void Move();
}
// 一种地图
class MountainMap implements Map {
public void Draw() {
System.out.println("MountainMap:Draw()");
}
public void Move() {
System.out.println("MountainMap:Move()");
}
}
// 另一种地图
class PlainMap implements Map {
public void Draw() {
System.out.println("PlainMap:Draw()");
}
public void Move() {
System.out.println("PlainMap:Move()");
}
}
// 地图工厂
abstract class MapFactory {
public static Map create(String type) {
if (type.equalsIgnoreCase("Mountain")) {
return new MountainMap();
} else if (type.equalsIgnoreCase("Plain")) {
return new PlainMap();
} else {
return null;
}
}
}
// 组合地图与坦克的接口
class TankGame {
Tank tank;
Map map;
public TankGame(Tank t, Map m) {
this.tank = t;
this.map = m;
}
public void Draw() {
// 其它逻辑
map.Draw();
}
public void Move() {
// 其它逻辑
map.Move();
}
public void Fire() {
// 其它逻辑
tank.fire();
}
}
public class Bridge {
public static void main(String[] args) {
Tank t = TankFactory.create(args[0]);
Map m = MapFactory.create(args[1]);
if ((t == null) || (m == null)) {
System.out.println("Parameter error");
return;
}
TankGame g = new TankGame(t, m);
g.Draw();
g.Move();
;
g.Fire();
}
}
这样,坦克与地图这两个维度独立变化,互无关联。当需要增加一种坦克或者地图时,只需要实现相应的接口即可。