其他分享
首页 > 其他分享> > 【笔记整理】图解设计模式 | 第12章 Decorator模式(装饰边框与被装饰物的一致性)

【笔记整理】图解设计模式 | 第12章 Decorator模式(装饰边框与被装饰物的一致性)

作者:互联网

【笔记整理】图解设计模式 | 导航


定义


Decorator模式中的登场角色

       Component角色定义了公共的接口(API)。

       该角色是实现了Component角色所定义的接口(API)的具体类。

       该角色具有与Component角色相同的接口(API)。在它内部保存了被装饰对象——Component角色。Decorator角色知道自己要装饰的对象。

       该角色是具体的Decorator角色。


Decorator模式的类图

关键点:


拓展思路的要点

       在Decorator模式中,装饰边框与被装饰物具有一致性。表示装饰边框的类是表示被装饰物的类的子类,体现了它们之间的一致性,它们具有相同的接口(API)。

       这样,即使被装饰物被边框装饰起来了,接口(API)也不会被隐藏起来。其他类依然可以调用接口的方法。这就是接口(API)的透明性

       得益于接口(API)的透明性,Decorator模式中也形成了类似于Composite模式中的递归结构。也就是说,装饰边框里面的“被装饰物”实际上又是别的物体的“装饰边框”。就像是剥洋葱时以为洋葱心要出来了,结果却发现还是皮。

       不过,Decorator模式虽然与Composite模式一样,都具有递归结构,但是它们的使用目的不同。Decorator模式的主要目的是通过添加装饰物来增加对象的功能。Composite模式的目的拥有关系(Composite模式是树形结构,Decorator模式俄罗斯套娃。)。

       在Decorator模式中,装饰边框与被装饰物具有相同的接口(API)。虽然接口(API)是相同的,但是越装饰,功能则越多。这样,我们就实现了不修改被装饰的类即可增加功能

       Decorator模式使用了委托。对“装饰边框”提出的要求(调用装饰边框的方法)会被转交(委托)给“被装饰物”去处理。

       Decorator模式中用到了委托,它使类之间形成了弱关联关系。因此,不用改变框架代码,就可以生成一个与其他对象具有不同关系的新对象。

       可以将一些功能非常简单的装饰边框,自由组合成为新的对象。

       除了java.io包以外,javax.swing.border包中也使用了Decorator模式,提供了可以为界面中的控件比那家装饰边框的类。


相关的设计模式

       Decorator模式可以在不改变被装饰物的接口(API)的前提下,为被装饰物添加边框(透明性)。

       Adapter模式用于适配两个不同的接口(API)。

       Decorator模式可以像改变被装饰物的边框或是被装饰物添加多重边框那样,来增加类的功能。

       Stragety模式通过整体地替换算法来改变类的功能。


延伸阅读:继承和委托中的一致性


代码

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));
		}
	}
}
/**
 * 显示单行字符串
 */
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 (0 == row) {
			return string;
		}
		return null;
	}

}
public abstract class Border extends Display {

	protected Display display;

	public Border(Display display) {
		this.display = display;
	}

}
public class SideBorder extends Border {

	private char borderChar;// 表示装饰边框的字符

	public SideBorder(Display display, char ch) { // 通过构造函数执行Display和装饰边框字符
		super(display);
		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;
	}

}
public class UpDownBorder extends Border {

	private char borderChar;// 表示装饰边框的字符

	public UpDownBorder(Display display, char ch) { // 通过构造函数执行Display和装饰边框字符
		super(display);
		borderChar = ch;
	}

	@Override
	public int getColumns() {
		return display.getColumns();
	}

	@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(int count) { // 生成一个重复count次字符ch的字符串
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < count; i++) {
			buf.append(borderChar);
		}
		return buf.toString();
	}
}
public class Main {

	public static void main(String[] args) {
		Display b1 = new StringDisplay("Hello, world.");
		Display b2 = new UpDownBorder(b1, '-');
		Display b3 = new SideBorder(b2, '*');
		b1.show();
		b2.show();
		b3.show();

		Display b4 = new FullBorder(new UpDownBorder(
				new SideBorder(new UpDownBorder(new SideBorder(new StringDisplay("Hello, world."), '*'), '='), '|'),
				'/'));
		b4.show();
	}

}

注:博客中的图片来自网上。

标签:12,display,边框,API,装饰物,设计模式,public,Decorator
来源: https://blog.csdn.net/jccg1000196340/article/details/88387023