0%

设计模式之结构型模式的设计与实现(二)

桥接模式

案例

​ 使用桥接模式模拟《Java 设计模式》教材 136 页图 10-4 所表达问题

抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 抽象类:抽象图像类
* @author Vincent
*/
public abstract class Image {
protected ImageImp imp;

/**
* 注入实现类接口对象
* @param imp
*/
public void setImageImp(ImageImp imp) {
this.imp = imp;
}

/**
* 模拟解析文件
* @param fileName
*/
public abstract void parseFile(String fileName);
}

扩充抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* 扩充抽象类:BMP格式图像类
* @author Vincent
*/
public class BMPImage extends Image {

/**
* 模拟解析BMP文件并获得一个像素矩阵对象m
* @param fileName
*/
@Override
public void parseFile(String fileName) {
Matrix m = new Matrix();
imp.doPaint(m);
System.out.println(fileName+",格式为BMP.");
}
}

/**
* 扩充抽象类:GIF格式图像类
* @author Vincent
*/
public class GIFImage extends Image {

/**
* 模拟解析GIF文件并获得一个像素矩阵对象m
* @param fileName
*/
@Override
public void parseFile(String fileName) {
Matrix m = new Matrix();
imp.doPaint(m);
System.out.println(fileName+",格式为GIF.");
}
}

/**
* 扩充抽象类:JPG格式图像类
* @author Vincent
*/
public class JPGImage extends Image {

/**
* 模拟解析JPG文件并获得一个像素矩阵对象m
* @param fileName
*/
@Override
public void parseFile(String fileName) {
Matrix m = new Matrix();
imp.doPaint(m);
System.out.println(fileName+",格式为JPG.");
}
}

/**
* 扩充抽象类:PNG格式图像类
* @author Vincent
*/
public class PNGImage extends Image {

/**
* 模拟解析PNG文件并获得一个像素矩阵对象m
* @param fileName
*/
@Override
public void parseFile(String fileName) {
Matrix m = new Matrix();
imp.doPaint(m);
System.out.println(fileName+",格式为PNG.");
}
}

实现类接口

1
2
3
4
5
6
7
8
9
10
11
/**
* 实现类接口:抽象操作系统实现类
* @author Vincent
*/
public interface ImageImp {
/**
* 显示像素矩阵m
* @param m
*/
public void doPaint(Matrix m);
}

具体实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* 具体实现类:Linux操作系统实现类
* @author Vincent
*/
public class LinuxImp implements ImageImp {
/**
* 调用Linux操作系统的绘制函数绘制像素矩阵
* @param m
*/
@Override
public void doPaint(Matrix m) {
System.out.println("在Linux操作系统中显示图像:");
}
}

/**
* 具体实现类:Unix操作系统实现类
* @author Vincent
*/
public class UnixImp implements ImageImp {
@Override
public void doPaint(Matrix m) {
System.out.println("在Unix操作系统中显示图像:");
}
}

/**
* 具体实现类:Windows操作系统实现类
* @author Vincent
*/
public class WindowsImp implements ImageImp {

/**
* 调用Windows操作系统的绘制函数绘制像素矩阵
* @param m
*/
@Override
public void doPaint(Matrix m) {
System.out.println("在Windows操作系统中显示图像:");
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 客户端类
* @author Vincent
*/
public class Client {
public static void main(String[] args) {
Image image;
ImageImp imp;
image = (Image) XMLUtil.getBean("image");
imp = (ImageImp) XMLUtil.getBean("os");
image.setImageImp(imp);
image.parseFile("小龙女");
}
}

小结

角色

  • Abstraction(抽象类)

​ 定义抽象类的接口,通常是抽象类而不是接口,其中定义了一个实现类接口类型的对象并可以维护该对象

  • RefinedAbstraction(扩充抽象类)

​ 扩充由抽象类定义的接口,调用在实现类接口定义的业务方法

  • Implementor(实现类接口)

​ 定义实现类的接口,不一定要与抽象类的接口完全一致。一般仅提供基本操作,而将具体实现交给子类

  • ConcreteImplementor(具体实现类)

​ 具体实现了实现类接口,在不同的具体实现类中提供了不同的实现

特点

​ 用组合关系代替继承关系,降低了抽象和实现这两个可变维度的耦合度

优点

  • 分离了抽象接口及其实现部分

  • 可以取代多层继承方案,极大地减少了子类的个数

  • 提高了系统的可扩展性,在两个变化维度中任意扩展一个维度而无需修改原有系统,符合开闭原则

缺点

  • 增加了系统理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程

  • 正确识别出系统中两个独立变化的维度并不是一件容易的事情

适用环境

  • 需要在抽象化和具体化之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系

  • 抽象部分和实现部分可以以继承的方式独立扩展而互不影响

  • 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立地进行扩展

  • 不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统