引言
装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。
这个模式我们应当最清楚不过了,不管是在写IO流时候还是在java.awt.Container#add(Component) (几乎广泛存在于 Swing 组件中)javax.faces.component.UIComponent#getChildren() (几乎广泛存在于 JSF UI 组件中)
那么我们自己写一个简单的例子来认识它
案例 读写文件
需求说明
我需要一个功能,不仅仅只是原模原样的读写文件,我有时候需要压缩或者手动加密
成员
Client:调用者
CompressionDecorator:压缩装饰
DataSource:读写文件接口
DataSourceDecorator:读写文件装饰类,这个是用来接收其他装饰对象来调用它的装饰方法
EncryptionDecorator:加密装饰
FileDataSource:最基本的文件读写
DataSource
public interface DataSource {
void writeData(String data);
String readData();
}
DataSourceDecorator
public class DataSourceDecorator implements DataSource{
private DataSource wrappee;
public DataSourceDecorator(DataSource wrappee) {
this.wrappee = wrappee;
}
@Override
public void writeData(String data) {
wrappee.writeData(data);
}
@Override
public String readData() {
return wrappee.readData();
}
}
CompressionDecorator
public class CompressionDecorator extends DataSourceDecorator {
private int compLevel = 6;
public CompressionDecorator(DataSource wrappee) {
super(wrappee);
}
@Override
public void writeData(String data) {
super.writeData(compress(data));
}
@Override
public String readData() {
return decompress(super.readData());
}
private String decompress(String readData) {
byte[] decode = Base64.decode(readData.getBytes());
InputStream in = new ByteArrayInputStream(decode);
InflaterInputStream inflaterInputStream = new InflaterInputStream(in);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(512);
int len;
try {
while ((len = inflaterInputStream.read()) != -1) {
byteArrayOutputStream.write(len);
}
in.close();
inflaterInputStream.close();
byteArrayOutputStream.close();
return new String(byteArrayOutputStream.toByteArray());
} catch (IOException e) {
return null;
}
}
private String compress(String data) {
byte[] bytes = data.getBytes();
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(512);
DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(outputStream, new Deflater(compLevel));
deflaterOutputStream.write(bytes);
outputStream.close();
deflaterOutputStream.close();
return Base64.encode(outputStream.toByteArray());
} catch (IOException ignored) {
return null;
}
}
public int getCompLevel() {
return compLevel;
}
public CompressionDecorator setCompLevel(int compLevel) {
this.compLevel = compLevel;
return this;
}
}
EncryptionDecorator
public class EncryptionDecorator extends DataSourceDecorator {
public EncryptionDecorator(DataSource wrappee) {
super(wrappee);
}
@Override
public void writeData(String data) {
super.writeData(encode(data));
}
@Override
public String readData() {
return decode(super.readData());
}
private String encode(String data){
byte[] bytes = data.getBytes();
for (int i = 0; i < bytes.length; i++) {
bytes[i] += 1;
}
return Base64.encode(bytes);
}
private String decode(String data){
byte[] decode = Base64.decode(data.getBytes());
for (int i = 0; i < decode.length; i++) {
decode[i] -= 1;
}
return new String(decode);
}
}
FileDataSource
public class FileDataSource implements DataSource{
private String name;
public FileDataSource(String name) {
this.name = name;
}
@Override
public void writeData(String data) {
try {
OutputStream outputStream = new FileOutputStream(new File(name));
outputStream.write(data.getBytes(),0,data.length());
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String readData() {
char[] buffer = null;
File file = new File(name);
try {
FileReader reader = new FileReader(file);
buffer = new char[(int) file.length()];
reader.read(buffer);
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
assert buffer != null;
return new String(buffer);
}
}
Client
public class Client {
public static void main(String[] args) {
String salaryRecords = "装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为";
DataSourceDecorator encoded =
new CompressionDecorator(new EncryptionDecorator(new FileDataSource("e:/OutputDemo.txt")));
encoded.writeData(salaryRecords);
System.out.println(encoded.readData());
DataSource plain = new FileDataSource("e:/OutputDemo.txt");
System.out.println("- Input ----------------");
System.out.println(salaryRecords);
System.out.println("- Encoded --------------");
System.out.println(plain.readData());
System.out.println("- Decoded --------------");
System.out.println(encoded.readData());
}
}
执行结果
这个例子中就可以发现压缩装饰或者加密装饰有很大的扩展性,可以删去也可以加一些其他的装饰来满足你的需求
结束语
装饰者模式目的就在于不再扩展局限于继承类这个地方,而是使用一种很巧妙的方式来加厚或减薄
你可以穿脱衣服来让你自己感觉舒适,代码也可以