【Java设计形式】Java实现桥接模式

【Java设计模式】Java实现桥接模式

不多说了,直接上代码。原代码是由一雨田使用C++写的,我改成了使用Java实现。


package cn.areful.designpattern.bridge;

/************************************************************************************************************\
 * 任务叙述:我们现在要实现一个画图系统,这个系统的需求暂时来说有以下几个:
 * 1、画圆、画长方形。(先实现画这两个形状) 
 * 2、已经有两个画图库了,这些画图库中定义了我们需要的操作,我们没必要重新去实现了
 * 3、我们的系统能够决定使用哪个的画图库中的操作
 * 根据以上的需求,我们的代码设计如下(这里先不使用Bridge模式,以便对比) :
 \************************************************************************************************************/

/************************************************************************************************************\
 * 两个画图库
 \************************************************************************************************************/
/** 画图库1 */
class DrawLib1 {
	public void DrawCircle() {
		System.out.println("DrawLib1,DrawCircle()");
	}

	public void DrawRectangle() {
		System.out.println("DrawLib1,DrawRectangle()");
	}

	public void DrawTriangle() {
		System.out.println("DrawLib1,DrawTriangle()");
	}
}

/** 画图库2 */
class DrawLib2 {
	public void DrawCircle() {
		System.out.println("DrawLib2,DrawCircle()");
	}

	public void DrawRectangle() {
		System.out.println("DrawLib2,DrawRectangle()");
	}

	public void DrawTriangle() {
		System.out.println("DrawLib2,DrawTriangle()");
	}
}

/************************************************************************************************************
 * \ 不使用桥接模式 \
 ************************************************************************************************************/
/** 通过绘图系统的接口,很容易抽象出来两个绘图库的绘图接口: */
abstract class Shape1 {
	public abstract void draw();

	protected DrawLib1 lib1;
}

abstract class Shape2 {
	public abstract void draw();

	protected DrawLib2 lib2;
}

/** 然后通过绘图库1和绘图库2的接口,实现画圆和画矩形: */
class Circle1 extends Shape1 {
	public Circle1() {
		lib1 = new DrawLib1();
	}

	@Override
	public void draw() {
		lib1.DrawCircle();
	}
}

class Rectangle1 extends Shape1 {
	public Rectangle1() {
		lib1 = new DrawLib1();
	}

	@Override
	public void draw() {
		lib1.DrawRectangle();
	}
}

class Circle2 extends Shape2 {
	public Circle2() {
		lib2 = new DrawLib2();
	}

	@Override
	public void draw() {
		lib2.DrawCircle();
	}
}

class Rectangle2 extends Shape2 {
	public Rectangle2() {
		lib2 = new DrawLib2();
	}

	@Override
	public void draw() {
		lib2.DrawRectangle();
	}
}

/** 调用库1的方法 */
class Draw1 {
	public Draw1(Shape1 s1) {
		s1.draw();
	}
}

/** 调用库2的方法 */
class Draw2 {
	public Draw2(Shape2 s2) {
		s2.draw();
	}
}

/** 不使用桥接方式,实现绘图系统 */
class NoBridge {
	public void test() {
		Circle1 c1 = new Circle1();
		Circle2 c2 = new Circle2();

		Rectangle1 r1 = new Rectangle1();
		Rectangle2 r2 = new Rectangle2();

		new Draw1(c1);
		new Draw1(r1);

		new Draw2(c2);
		new Draw2(r2);
	}
}

/************************************************************************************************************
 * \ 好的,上述的代码运行正常,如果不需要维护的话,我们就不用管它拉~~ 但是,代码是一定要维护的,逃不过的宿命。 出现变化的地方可能是这样的:
 * 1、出现了第三个库 2、画图系统需要画三角形 这个时候,我们再看看要完成这两个变化我们需要作的修改,就会发现,我要晕了
 * (当一个程序员要晕的时候,也就是BUG要出现的时候了) \
 ************************************************************************************************************/

/************************************************************************************************************
 * 好了,现在让我们使用Bridge模式来实现上面的系统<br>
 * Bridge模式最重要是把表示和实现分开
 ************************************************************************************************************/

/** 抽象出两个库中画圆,和画矩形的方法,为接口ShapeImp */
interface ShapeImp {
	public void DrawCircle();

	public void DrawRectangle();
}

/** 通过ShapeImp接口实现对库1的调用 */
class ShapeImp1 implements ShapeImp {
	public void DrawCircle() {
		dlib1.DrawCircle();
	}

	public void DrawRectangle() {
		dlib1.DrawRectangle();
	}

	private DrawLib1 dlib1 = new DrawLib1();
}

/** 通过ShapeImp接口实现对库2的调用 */
class ShapeImp2 implements ShapeImp {
	public void DrawCircle() {
		dlib2.DrawCircle();
	}

	public void DrawRectangle() {
		dlib2.DrawRectangle();
	}

	private DrawLib2 dlib2 = new DrawLib2();
}

/** 将"画圆"抽象到Circle类中 */
class Circle {
	private ShapeImp shape;

	public Circle(ShapeImp shape) {
		this.shape = shape;
	}

	public void draw() {
		shape.DrawCircle();
	}
}

/** 将"画矩形"抽象到Rectangle类中 */
class Rectangle {
	private ShapeImp shape;

	public Rectangle(ShapeImp shape) {
		this.shape = shape;
	}

	public void draw() {
		shape.DrawRectangle();
	}
}

/************************************************************************************************************
 * \
 * 
 * ClassName: Bridge<br>
 * Description: 使用"桥接"模式重新实现画图系统
 * <p>
 * 
 * 再考虑下面的需求:<br>
 * 1.出现了第三个库<br>
 * 2.画图系统需要新增一个画三角形的方法
 * <p>
 * 
 * 针对对一个需求,只需添加一个ShapeImg就可以了。<br>
 * 针对第二个需求,只需添加一个Triangle类就可以了。<br>
 * 可以看出来,变化不再造成混乱,只需要单独针对变化改动代码就行了。<br>
 * 也就是,变化被Bridge给分开了。<br>
 * 
 * @author gaojian email:gaojian@raiyi.com
 * @version
 * @since Ver 1.1
 * @Date 2013 2013-10-28 下午1:58:13
 * @see \
 ************************************************************************************************************/
class Bridge {
	public void test() {
		ShapeImp s1 = new ShapeImp1();

		Circle c1 = new Circle(s1);
		c1.draw();

		Rectangle r1 = new Rectangle(s1);
		r1.draw();

		ShapeImp s2 = new ShapeImp2();

		Circle c2 = new Circle(s2);
		c2.draw();

		Rectangle r2 = new Rectangle(s2);
		r2.draw();
	}
}

/** 测试使用桥接模式,和不使用桥接模式实现的画图系统 */
public class BridgeTest {
	public static void main(String[] args) {

		/** 为true,测试使用桥接模式,否则,测试不使用桥接模式 */
		final boolean isbridget = true;
		if (isbridget) {
			Bridge b = new Bridge();
			b.test();
		} else {
			NoBridge b = new NoBridge();
			b.test();
		}
	}
}