结构型-桥接模式 Link to heading
桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。
【GOF95】在提出桥梁模式的时候指出,桥梁模式的用意是"将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化"。这句话有三个关键词,也就是抽象化、实现化和脱耦。
下列各语言的代码都用于写出两个不同的圆的坐标和半径。
/** "Implementor" */
interface DrawingAPI{
public void drawCircle(double x, double y, double radius);
}
/** "ConcreteImplementor" 1/2 */
class DrawingAPI1 implements DrawingAPI{
public void drawCircle(double x, double y, double radius){
System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
}
}
/** "ConcreteImplementor" 2/2 */
class DrawingAPI2 implements DrawingAPI{
public void drawCircle(double x, double y, double radius){
System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
}
}/** "Abstraction" */
interface Shape{
public void draw(); // low-level
public void resizeByPercentage(double pct); // high-level
}
/** "Refined Abstraction" */
class CircleShape implements Shape{
private double x, y, radius;
private DrawingAPI drawingAPI;
public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI){
this.x = x; this.y = y; this.radius = radius;
this.drawingAPI = drawingAPI;
}
// low-level i.e. Implementation specific
public void draw(){
drawingAPI.drawCircle(x, y, radius);
}
// high-level i.e. Abstraction specific
public void resizeByPercentage(double pct){
radius *= pct;
}
}
/** "Client" */
class BridgePattern{
public static void main(String[] args){
Shape[] shapes = new Shape[2];
shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1());
shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2());
for (Shape shape : shapes){
shape.resizeByPercentage(2.5);
shape.draw();
}
}
}
场景模拟 Link to heading
在购买奶茶的时候,店员首先会问我们,您需要什么类型的奶茶,比如我们此时点了一杯啵啵芋圆奶茶,接着店员会直接问我们需要大杯、中杯还是小杯,最后还会询问我们需要加什么配料,比如椰果、珍珠等,最后才会给我们制作奶茶。
最初设计 Link to heading
public interface Tea { //由具体类型的奶茶实现
String getType(); //不同的奶茶返回的类型不同
}
public interface Size { //分大杯小杯中杯
String getSize();
}
/**
* 大杯芋圆啵啵奶茶
*/
public class LargeKissTea implements Tea, Size{
@Override
public String getSize() {
return "大杯";
}
@Override
public String getType() {
return "芋圆啵啵奶茶";
}
}
现在一共有两个维度需要考虑,那么我们岂不是得一个一个去创建这些类?甚至如果还要考虑配料,那么光创建类就得创建不知道多少个了。
改进方案 Link to heading
public abstract class AbstractTea {
protected Size size; //尺寸作为桥接属性存放在类中
protected AbstractTea(Size size){ //在构造时需要知道尺寸属性
this.size = size;
}
public abstract String getType(); //具体类型依然是由子类决定
public String getSize(){ //添加尺寸维度获取方式
return size.getSize();
}
}
// 单独为Size创建子类
public class Large implements Size{
@Override
public String getSize() {
return "大杯";
}
}
// 芋圆波波
public class KissTea extends AbstractTea{ //创建一个啵啵芋圆奶茶的子类
protected KissTea(Size size) { //在构造时需要指定具体的大小实现
super(size);
}
@Override
public String getType() {
return "啵啵芋圆奶茶"; //返回奶茶类型
}
}
// 使用
public static void main(String[] args) {
KissTea tea = new KissTea(new Large());
System.out.println(tea.getType());
System.out.println(tea.getSize());
}
通过桥接模式,使得抽象和实现可以沿着各自的维度来进行变化,不再是固定的绑定关系。