動態的給一個對象添加一些額外的職責。就增長功能來講,Decorator模式相比生成子類更爲靈活java
在某些狀況下,咱們可能會「過分的使用繼承來擴展對象的功能」。繼承是靜態的,沒法在運行時更改已有對象的行爲,只能使用由不一樣子類建立的對象來替代當前的整個對象;而且隨着子類的增多(擴展功能的增多),各類子類的組合(擴展功能的組合)會致使子類的膨脹app
1) 比靜態繼承更加靈活ide
2) 能夠在運行時,添加和刪除對象功能函數
3) 避免在層次結構高層的類有太多的特徵學習
4) 有不少小對象。 對了解系統的人來講,很容易對它們進行定製,可是很難學習這些系統,排錯也很困難this
decorators/DataSource.java: 定義了讀取和寫入操做的通用數據接口加密
package decorator.decorators; /** * @author GaoMing * @date 2021/7/12 - 16:48 */ public interface DataSource { void writeData(String data); String readData(); }
decorators/FileDataSource.java: 簡單數據讀寫器spa
package decorator.decorators; import java.io.*; /** * @author GaoMing * @date 2021/7/12 - 16:49 */ public class FileDataSource implements DataSource{ private String name; public FileDataSource(String name) { this.name = name; } @Override public void writeData(String data) { File file = new File(name); try (OutputStream fos = new FileOutputStream(file)) { fos.write(data.getBytes(), 0, data.length()); } catch (IOException ex) { System.out.println(ex.getMessage()); } } @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()); } return new String(buffer); } }
decorators/DataSourceDecorator.java: 抽象基礎裝飾3d
package decorator.decorators; /** * @author GaoMing * @date 2021/7/12 - 16:51 */ public class DataSourceDecorator implements DataSource{ private DataSource wrappee; DataSourceDecorator(DataSource source) { this.wrappee = source; } @Override public void writeData(String data) { wrappee.writeData(data); } @Override public String readData() { return wrappee.readData(); } }
decorators/EncryptionDecorator.java: 加密裝飾代理
package decorator.decorators; import java.util.Base64; /** * @author GaoMing * @date 2021/7/12 - 16:53 */ public class EncryptionDecorator extends DataSourceDecorator{ public EncryptionDecorator(DataSource source) { super(source); } @Override public void writeData(String data) { super.writeData(encode(data)); } @Override public String readData() { return decode(super.readData()); } private String encode(String data) { byte[] result = data.getBytes(); for (int i = 0; i < result.length; i++) { result[i] += (byte) 1; } return Base64.getEncoder().encodeToString(result); } private String decode(String data) { byte[] result = Base64.getDecoder().decode(data); for (int i = 0; i < result.length; i++) { result[i] -= (byte) 1; } return new String(result); } }
decorators/CompressionDecorator.java: 壓縮裝飾
package decorator.decorators; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Base64; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; /** * @author GaoMing * @date 2021/7/12 - 16:54 */ public class CompressionDecorator extends DataSourceDecorator{ private int compLevel = 6; public CompressionDecorator(DataSource source) { super(source); } public int getCompressionLevel() { return compLevel; } public void setCompressionLevel(int value) { compLevel = value; } @Override public void writeData(String data) { super.writeData(compress(data)); } @Override public String readData() { return decompress(super.readData()); } private String compress(String stringData) { byte[] data = stringData.getBytes(); try { ByteArrayOutputStream bout = new ByteArrayOutputStream(512); DeflaterOutputStream dos = new DeflaterOutputStream(bout, new Deflater(compLevel)); dos.write(data); dos.close(); bout.close(); return Base64.getEncoder().encodeToString(bout.toByteArray()); } catch (IOException ex) { return null; } } private String decompress(String stringData) { byte[] data = Base64.getDecoder().decode(stringData); try { InputStream in = new ByteArrayInputStream(data); InflaterInputStream iin = new InflaterInputStream(in); ByteArrayOutputStream bout = new ByteArrayOutputStream(512); int b; while ((b = iin.read()) != -1) { bout.write(b); } in.close(); iin.close(); bout.close(); return new String(bout.toByteArray()); } catch (IOException ex) { return null; } } }
Demo.java: 客戶端代碼
package decorator; import decorator.decorators.*; /** * @author GaoMing * @date 2021/7/12 - 17:03 */ public class Demo { public static void main(String[] args) { String salaryRecords = "Name,Salary\nJohn Smith,100000\nSteven Jobs,912000"; DataSourceDecorator encoded = new CompressionDecorator( new EncryptionDecorator( new FileDataSource("out/OutputDemo.txt"))); encoded.writeData(salaryRecords); DataSource plain = new FileDataSource("out/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()); } }
運行結果
- Input ---------------- Name,Salary John Smith,100000 Steven Jobs,912000 - Encoded -------------- Zkt7e1Q5eU8yUm1Qe0ZsdHJ2VXp6dDBKVnhrUHtUe0sxRUYxQkJIdjVLTVZ0dVI5Q2IwOXFISmVUMU5rcENCQmdxRlByaD4+ - Decoded -------------- Name,Salary John Smith,100000 Steven Jobs,912000
(轉載)
識別方法: 裝飾可經過以當前類或對象爲參數的建立方法或構造函數來識別