作用:装饰器模式,动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。Java I/O 中就应用了这一模式(如FilterInputStream,FilterOutputStream)。
示例-装饰器模式:
示例1(比较直观)
//------------------------------------------接口Work 和类SquarePeg ---------------------------------------------------------------
package decorator_1;
public interface Work
{
public void insert();
}
package decorator_1;
public class SquarePeg implements Work{
public void insert(){
System.out.println("方形桩插入");
}
}
/*
* 接口Work有一个具体实现:插入方形桩或圆形桩,这两个区别对Decorator是
*无所谓.我们以插入方形桩为例
*/
//------------------------------------------Decorator类---------------------------------------------------------------
package decorator_1;
public class Decorator implements Work {
private Work work;
// 在构造器中使用组合new方式,引入Work对象;
public Decorator(Work work) {
this.work = work;
}
public void insert() {
System.out.println("挖坑");
work.insert();
System.out.println("钉木板");
}
}
/*
* 现在有一个应用:需要在桩打入前,挖坑,在打入后,在桩上钉木板
*/
//------------------------------------------测试类---------------------------------------------------------------
package decorator_1;
public class Main {
public static void main(String[] args) {
Work work1 = new SquarePeg();
work1.insert();
System.out.println("--------经过装饰后~----------");
Work work2 = new Decorator(work1);
work2.insert();
}
}
示例2(比较实际)
类一览表;
名称 |
说明 |
Display |
打印字符串的抽象类 |
StringDisplay |
只有一行的打印字符串用的类-相当于核心对象 |
Border |
表示“装饰外框”的抽象类-装饰器抽象类 |
SideBorder |
在左右外框加上装饰外框的类-装饰器具体类1 |
FullBorder |
在上下外框加上装饰外框的类-装饰器具体类2 |
Main |
测试用的类 |
类图查看图片附件:类图-Decorator _1
//------------------------------------------ Display类---------------------------------------------------------------
package decorator_2;
public abstract class Display{
public abstract int getColumns();//取得横向的字数
public abstract int getRows();//取得纵向的行数
public abstract String getRowText(int row);//取得第row个字符串
public final void show(){ //打印所用内容
for (int i = 0; i < getRows(); i++){
System.out.println(getRowText(i));//row==0,设计是从这里开始的~~
}
}
}
//------------------------------------------ StringDisplay类---------------------------------------------------------------
package decorator_2;
public class StringDisplay extends Display{
private String string;
public StringDisplay(String string){
this.string = string;
}
public int getColumns(){
return string.getBytes().length;
}
public int getRows(){
return 1;
}
public String getRowText(int row){
if (row == 0) {
return string;
} else {
return null;
}
}
}
//------------------------------------------ Border类---------------------------------------------------------------
package decorator_2;
public abstract class Border extends Display{
protected Display display; //指定装饰外框里面的“内容”
protected Border(Display display){//在产生对象实例时,以参数内容指定“内容”
this.display = display;
}
}
//------------------------------------------ SideBorder类---------------------------------------------------------------
package decorator_2;
public class SideBorder extends Border{
private char borderChar; //装饰字符
public SideBorder(Display display, char ch){
super(display);//以构造函数指定Display和装饰字符
this.borderChar = ch;
}
public int getColumns() {//字符要加上内容两边的装饰字符
return 1 + display.getColumns() + 1;
}
public int getRows(){ //行数同内容的行数
return display.getRows();
}
public String getRowText(int row){//指定该行的内容,即在内容指定行的两边加上装饰字符
return borderChar + display.getRowText(row) + borderChar;
}
}
//------------------------------------------ FullBorder类---------------------------------------------------------------
package decorator_2;
public class FullBorder extends Border{
public FullBorder(Display display){
super(display);
}
public int getColumns(){ //字数=内容字数+内容两边的装饰字符
return 1 + display.getColumns() + 1;
}
public int getRows(){ //行数=内容行数+上下是装饰字符
return 1 + display.getRows() + 1;
}
public String getRowText(int row){ //指定该行的内容
if (row == 0) {//外框顶端
return "+" + makeLine('-',display.getColumns()) + "+";
} else if (row == display.getRows() + 1) {//外框底端
return "+" + makeLine('-',display.getColumns()) + "+";
}else{//其他部分
return "|" + display.getRowText(row - 1) + "|";
}
}
private String makeLine(char ch, int count){//已字符ch,建立重复count次的连续字符串
StringBuffer buf = new StringBuffer();
for(int i =0; i < count; i++){
buf.append(ch);
}
return buf.toString();
}
}
//------------------------------------------测试类---------------------------------------------------------------
package decorator_2;
public class Main{
public static void main(String[] args){
Display b1 = new StringDisplay("Hello ,world.");//打印“Hello,world”没有任何装饰
b1.show();
Display b2 = new SideBorder(b1, '#');//把装饰符”#“加在b1的两边
b2.show();
Display b3 = new FullBorder(b2); //把b2去不加上装饰外框
b3.show();
// Display b4 =
// new SideBorder(
// new FullBorder(
// new FullBorder(
// new SideBorder(
// new FullBorder(
// new StringDisplay("您好。")
// ),
// '*'
// )
// )
// ),
// '/'
// );
// b4.show();
}
}
解析:
装饰器模式对装饰外框和内容是一视同仁的,就如在程序示例中表示装饰外框的Border类是表示内容的Display的子类,这既是一视同仁,换句话说,Border类(及其子类)具有内容表示内容类Display相同的接口。
装饰器模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案,提供比继承更多的灵活性。动态给一个对象增加功能,这些功能可以再动态的撤消,增加由一些基本功能的排列组合而产生的非常大量的功能。就如我们每个人穿衣服一样,我们个体是不变的核心对象,穿上不同样式的衣服(这就是装饰),就能完成我们想要的视觉效果(所需的对象)。