本文共 4637 字,大约阅读时间需要 15 分钟。
装饰模式是不断地为对象添加装饰的设计模式。比如有一个蛋糕,添加了奶油后就是奶油蛋糕。再添加一些草莓后,就是草莓奶油蛋糕。
程序中的对象与蛋糕十分相似。首先有一个相当于蛋糕的对象,然后像不断的装饰蛋糕一样地不断对其增加功能,它就编程了使用目的更加明确的对象。
先来看一个例子吧,给一行字符串添加左右边框、上线边框。
类图
代码 Display(显示字符串的抽象类,即被装饰的对象抽象类):public abstract class Display { abstract int getColumns();//获取横向字符数 abstract int getRows();//获取纵向字符数 abstract String getRowText(int i);//获取第row行的字符串 /** * 显示所有字符 */ public final void show() { for (int i=0; i
StringDisplay(显示字符串的实现类,即被装饰的对象):
public class StringDisplay extends Display { //要显示的字符串 private String string; public StringDisplay(String string) { this.string = string; } @Override int getColumns() { return string.getBytes().length; //字符数 } @Override int getRows() { return 1; //行数为1 } @Override String getRowText(int row) { if (row == 0) { return string;//仅当row为0时返回值 } return null; }}
Border(显示装饰边框的抽象类,即装饰对象的抽象类):
public abstract class Border extends Display { protected Display display;//被装饰对象,装饰类必须持有该对象 protected Border(Display display) { this.display = display; }}
SideBorder(装饰左右边框,即装饰对象):
public class SiderBorder extends Border { //装饰边框的字符 private char borderChar; public SiderBorder(Display display, char ch) { super(display); borderChar = ch; } /** * 字符数为字符串字符数加上两侧边框字符数 * @return */ @Override int getColumns() { return 1 + display.getColumns() + 1; } /** * 行数即被装饰物的行数 * @return */ @Override int getRows() { return display.getRows(); } /** * 指定的那一行的字符串为被装饰物的字符串加上两侧边框的字符 * @param i * @return */ @Override String getRowText(int i) { return borderChar + display.getRowText(i) + borderChar; }}
FullBorder(装饰上下边框,即装饰对象):
public class FullBorder extends Border { public FullBorder(Display display) { super(display); } /** * 字符数为字符串字符数加上两侧边框字符数 * @return */ @Override int getColumns() { return 1 + display.getColumns() + 1; } /** * 行数即被装饰物的行数 * @return */ @Override int getRows() { return 1 + display.getRows() + 1; } /** * 指定的那一行的字符串 * @param i * @return */ @Override String getRowText(int i) { if (i == 0) { return "+" + makeLine('-', display.getColumns()) + "+";//下边框 } else if (i == display.getRows()+1) { return "+" + makeLine('-', display.getColumns()) + "+";//上边框 } else { return "|" + display.getRowText(i - 1) + "|";//其他边框 } } /** * 生成一个重复count次的字符ch的字符串 * @param ch * @param count * @return */ private String makeLine(char ch, int count) { StringBuffer buf = new StringBuffer(); for (int i=0; i
DecoratorMain(测试类):
public class DecoratorMain { public static void main(String[] args) { //依次不断地装饰 Display b1 = new StringDisplay("Hello,world."); Display b2 = new SiderBorder(b1, '#'); Display b3 = new FullBorder(b2); b1.show(); b2.show(); b3.show(); //循环装饰 Display b4 = new SiderBorder( new FullBorder( new FullBorder( new SiderBorder( new FullBorder( new StringDisplay("你好,世界。") ), '*' ) ) ), '/' ); b4.show(); }}
测试结果:
Hello,world.#Hello,world.#+--------------+|#Hello,world.#|+--------------+/+------------------------+//|+----------------------+|//||*+------------------+*||//||*|你好,世界。|*||//||*+------------------+*||//|+----------------------+|//+------------------------+/
java.io包中的很多类都用到了装饰模式。比如:
Reader reader = new FileReader("test.txt");Reader reader = new BufferedReader(new FileReader("test.txt"));Reader reader = new LineNumberReader( new BufferedReader( new FileReader("test.txt")));
转载地址:http://jwpxi.baihongyu.com/