装饰者模式
概述
在程序开发设计中,开闭原则是一个非常重要的原则,他要求类应该对扩展开放,对修改关闭,而装饰者模式就是这一原则的最佳实现。
装饰者模式顾名思义,就是很多不同的“装饰品”来修饰某一个主体,比如同样都是蛋糕,被奶油装饰的蛋糕叫做“奶油蛋糕”,在加一块饼干叫做“奶油饼干蛋糕”,再加一块巧克力叫做“巧克力奶油饼干蛋糕”。
装饰者模式动态的将责任附加到了对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案
示例程序
来通过一段示例程序了解一下装饰者模式
我们要完成一下功能,定义一个字符串,如果用SideBorder装饰,会出现以下效果
#YellowStar#
如果用FullBorder装饰,会出现以下效果
+----------+
|YellowStar|
+----------+
名字 | 说明 |
---|---|
Display | 用于显示字符串的抽象类 |
StringDisplay | 用于显示单行字符串的类,继承Display |
Border | 用于显示装饰边框的抽象类 |
SideBorder | 只显示左右两边框的类 |
FullBorder | 显示上下左右边框的累 |
UML类图
代码实现
Display
public abstract class Display {
//获取横向字符串数
public abstract int getColumns();
//获取纵向行数
public abstract int getRows();
//获取第row行的字符串
public abstract String getRowText(int row);
public final 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() {
return 1;
}
@Override
public String getRowText(int row) {
if (row == 0) {
return string;
}
return null;
}
}
Border
display设置成protected,为了让他的子类可以使用
public abstract class Border extends Display{
protected Display display;
public Border(Display display) {
this.display = display;
}
}
SideBorder
public class SideBorder extends Border{
private char borderChar;
public SideBorder(Display display, char borderChar) {
super(display);
this.borderChar = borderChar;
}
@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 c , int count){
StringBuffer sb = new StringBuffer();
for (int i = 0; i < count; i++) {
sb.append(c);
}
return sb.toString();
}
}
test
@SpringBootTest
class Practice1200ApplicationTests {
@Test
void contextLoads() {
Display d1 = new StringDisplay("YellowStar");
Display d2 = new SideBorder(d1,'#');
Display d3 = new FullBorder(d2);
d1.show();
System.out.println();
d2.show();
System.out.println();
d3.show();
System.out.println();
Display d4 = new FullBorder(
new SideBorder(
new FullBorder(
new SideBorder(
new FullBorder(
new StringDisplay("YELLOWSTAR")
),'#'
)
),'#'
)
);
d4.show();
}
}
//输出
YellowStar
#YellowStar#
+------------+
|#YellowStar#|
+------------+
+------------------+
|#+--------------+#|
|#|#+----------+#|#|
|#|#|YELLOWSTAR|#|#|
|#|#+----------+#|#|
|#+--------------+#|
+------------------+