设计模式(八)桥接模式

适配器模式属于结构型模式的一种。

首先试想一个问题:
需要开发一个跨平台的图片浏览系统,需要支持Windows、Linux、Android等系统,同时还要支持多种类型的文件JPG、BMP、GIF等。系统需要能够灵活添加新的文件格式和操作系统支持。

正常情况下首先想到的是如下图的类结构:

上图的结构是通过继承来实现“操作系统”和“文件类型”两个维度的组合,这种方式导致程序中的类数量过多(操作系统数量x文件类型数量),而且违反了“单一职责原则”,不利于系统的扩展。

再提出另外一个类似的问题,并解决该问题:
开发一个数据转换工具,可以将数据库中的数据转换成多种文件格式,例如txt、xml、pdf等格式,同时该工具需要支持多种不同的数据库。

问题需要开发一个数据转换工具(DataConverter),需要对“文件格式”、“数据库类型”两个维度进行分离,分离方式是:对于不同文件格式可以继承DataConverter,实现多种文件类型的转换器(XmlDataConverter、JsonDataConverter…),对于数据库类型可以定义一个OraginalDataReader接口,通过实现该接口来实现多种数据库支持(OracleDataReader、MysqlDataReader)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package info.aviraer.design_pattern.structure.bridge;

import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;

/**
* Created by Aviraer on 2018/3/14.
*/
public abstract class DataConverter {

private OriginalDataReader originalDataReader;

public abstract void transform(OutputStream transformedDataOutput);

public OriginalDataReader getOriginalDataReader() {
return originalDataReader;
}

public void setOriginalDataReader(OriginalDataReader originalDataReader) {
this.originalDataReader = originalDataReader;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package info.aviraer.design_pattern.structure.bridge;

import java.io.InputStream;
import java.io.OutputStream;

/**
* Created by Aviraer on 2018/3/14.
*/
public class JsonDataConverter extends DataConverter{

@Override
public void transform(OutputStream transformedDataOutput) {
System.out.println("开始转换数据为Json格式文件");
InputStream inputStream = this.getOriginalDataReader().read();
//transformedDataOutput.write();
System.out.println("转换数据为Json格式文件完成");
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package info.aviraer.design_pattern.structure.bridge;

import java.io.InputStream;
import java.io.OutputStream;

/**
* Created by Aviraer on 2018/3/14.
*/
public class XmlDataConverter extends DataConverter{

@Override
public void transform(OutputStream transformedDataOutput) {
System.out.println("开始转换数据为Xml格式文件");
InputStream inputStream = this.getOriginalDataReader().read();
//transformedDataOutput.write();
System.out.println("转换数据为Xml格式文件完成");
}

}
1
2
3
4
5
6
7
8
9
10
11
12
package info.aviraer.design_pattern.structure.bridge;

import java.io.InputStream;

/**
* Created by Aviraer on 2018/3/14.
*/
public interface OriginalDataReader {

public InputStream read();

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package info.aviraer.design_pattern.structure.bridge;

import java.io.InputStream;

/**
* Created by Aviraer on 2018/3/14.
*/
public class MysqlOriginalDataReader implements OriginalDataReader{

@Override
public InputStream read() {
System.out.println("读取Mysql数据库数据");
return null;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package info.aviraer.design_pattern.structure.bridge;

import java.io.InputStream;

/**
* Created by Aviraer on 2018/3/14.
*/
public class OracleOriginalDataReader implements OriginalDataReader{

@Override
public InputStream read() {
System.out.println("读取Oracle数据库数据");
return null;
}

}

优点
1.分离抽象接口及实现部分,可以更灵活的多维度组合对象
2.取代多层继承,减少子类数量,更加符合“单一职责原则”

缺点
1.增加理解难度,且在设计阶段就要做好规划