Decorator 模式

mac2026-03-13  4

Decorator 模式

不断地为对象添加装饰的设计模式被称为Decorator 模式。

示例程序类图

示例程序

Display

public abstract class Display { public abstract int getColumns(); // 获取横向字符数 public abstract int getRows(); // 获取纵向行数 public abstract String getRowText(int row); // 获取第row行的字符串 public void show() { // 全部显示 for (int i = 0; i < getRows(); i++) { System.out.println(getRowText(i)); } } }

StringDisplay

public class StringDisplay extends Display { private String string; // 要显示的字符串 public StringDisplay(String string) { // 通过参数传入要显示的字符串 this.string = string; } @Override public int getColumns() { // 字符数 return string.getBytes().length; } @Override public int getRows() { // 行数是1 return 1; } @Override public String getRowText(int row) { // 仅当row为0时返回值 if (row == 0) { return string; } else { return null; } } }

Border

public abstract class Border extends Display { protected Display display; // 表示被装饰物 protected Border(Display display) { // 在生成实例时通过参数指定被装饰物 this.display = display; } }

SideBorder

public class SideBorder extends Border { private char borderChar; // 表示装饰边框的字符 public SideBorder(Display display, char ch) { // 通过构造函数指定Display和装饰边框字符 super(display); this.borderChar = ch; } @Override public int getColumns() { // 字符数为字符串字符数加上两侧边框字符数 return 1 + display.getColumns() + 1; } @Override public int getRows() { // 行数即被装饰物的行数 return display.getRows(); } @Override public String getRowText(int row) { // 指定的那一行的字符串为被装饰物的字符串加上两侧的边框的字符 return borderChar + display.getRowText(row) + borderChar; } }

FullBorder

public class FullBorder extends Border { public FullBorder(Display display) { super(display); } @Override public int getColumns() { // 字符数为被装饰物的字符数加上两侧边框字符数 return 1 + display.getColumns() + 1; } @Override public int getRows() { // 行数为被装饰物的行数加上上下边框的行数 return 1 + display.getRows() + 1; } @Override 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) { // 生成一个重复count次字符ch的字符串 StringBuffer buf = new StringBuffer(); for (int i = 0; i < count; i++) { buf.append(ch); } return buf.toString(); } }

Main

public class Main { public static void main(String[] args) { Display b1 = new StringDisplay("Hello, world."); Display b2 = new SideBorder(b1, '#'); Display b3 = new FullBorder(b2); b1.show(); b2.show(); b3.show(); Display b4 = new SideBorder( new FullBorder( new FullBorder( new SideBorder( new FullBorder( new StringDisplay("你好,世界。") ), '*' ) ) ), '/' ); b4.show(); } }

Decorator 模式中的登场角色

1.Component

增加功能时的核心角色。在示例程序中,由Display类扮演此角色。

2.ConcreteComponent

该角色是实现了Component角色所定义的接口(API)的具体蛋糕。在示例程序中,由StringDisplay类扮演此角色。

3.Decorator(装饰物)

该角色具有与Component角色相同的接口(API)。在它内部保存了被装饰对象——Component角色。Decorator角色知道自己要装饰的对象。在示例程序中,由Border类扮演此角色。

4.ConcreteDecorator(具体的装饰物)

该角色是具体的Decorator角色。在示例程序中,由SideBorder和FullBorder类扮演此角色。

通用类图

Decorator 模式的主要目的是通过添加装饰物来增加对象的功能。

继承和委托中的一致性

public class Parent { void parentMethod(){ System.out.println("Parent"); } } public class Child extends Parent { private String namec = "child"; void childMethod() { System.out.println("Child"); } public static void main(String[] args) { // 输出Parent,parent Parent obj = new Child(); obj.parentMethod(); System.out.println(obj.name); // 输出Child Parent obj1 = new Child(); ((Child) obj1).childMethod(); } }

从上面的代码中,我们可以看到Child类的实例可以被保存在Parent类型的变量中,也可以调用从Parent类中继承的方法。 我们可以像操作Parent类的实例一样操作Child类的实例。这是将子类当作父类看待的一个例子。 但是反过来,如果想将父类当作子类一样操作,则需要先进行类型转换。

最新回复(0)