Java/软件构造 设计模式-Decorator(装饰器)

近日软件构造的实验中介绍了一种特殊的设计模式-Decorator,之所以说它特殊,是因为Decorator(装饰器)设计模式是一种自己Delegates(委派)自己的模式,同时正是因为这种属性使得它变得相对其他模式难以理解。
提示:需要先了解Delegation!!!

Decorator模式用于设计描述多种特性,类似于穿衣服,每件衣服会有不同的特性,比如保暖的最内层衣服,正常的打底衣服,以及外面用来装逼的风衣(划掉)。那可能有人马上想到,那直接继承啊,一个父类,几个子类,完全够应付了。确实,但是考虑到可能会有很多子类,而且可能每次你并不会用到所有的子类,比如夏天你可能只需要一条小裤衩,这样一个小裤衩也会是一个继承分支。这样一来就会导致组合爆炸的问题,即可能会产生一颗很大的继承树,以及大量的重复性代码,其可复用性很低,修改的代价高昂,即每次需要修改所有的同样代码的子类,或者增加新的子类十分麻烦。这样Decorator模式应运而生,即一种可以随意组合穿搭的模式。这种模式如何设计呢?其UML图如下:
在这里插入图片描述
事实上当一个事物有较多属性才会显出这个模式的优点,为了介绍方便,这里只有两个特性。

1.首先看接口AA是一个接口,里面只有一个方法print(),即打印一个字符串。

public interface A {
	public void print();
}

2.然后便是一个很简单的实现类concreteA实现了这个接口。里面实现了唯一的方法,并打印出一个字符串“concreteA”

public class concreteA implements A{
	@Override
	public void print() {
		System.out.println("concrete A");
	}
}

接下来便是对于这个concreteA的装饰部分!!!
3.首先是一个抽象类B实现了接口A,并且委派concreteA给自己做了print这个事情。
(1)首先在里面定义一个concreteA类型的参数tmp,并把它传入B中。
(2)实现接口A的print方法,这里直接使用concreteA的实现而不需要自己做。

public abstract class B implements A{
	A tmp;
	public B(A tmp) {
		this.tmp = tmp;
	}
	@Override
	public void print() {
		tmp.print();
	}
}

4.假设concreteA有两个属性,其中一个为dA,这里dA继承抽象类B,那么直接使用B中的tmp为自己的参数。然后直接使用父类B的print方法作为自己print方法的基础实现,并增加一个特性,即输出“dA”。

public class dA extends B {
	public dA(A tmp) {
		super(tmp);
	}
	@Override
	public void print() {
		super.print();
		System.out.println("dA");
	}
}

5.同理实现另外一个特性dB,增加自己的特性,输出“dB”。

public class dB extends B{
	public dB(A tmp) {
		super(tmp);
	}
	@Override
	public void print() {
		super.print();
		System.out.println("dB");
	}
}

那么写到这里,整个设计已经完成,接下来看看如何使用。
(1)首先实例化一个基础的实现,即concreteA
(2)然后可以使用其特性类包装它,任意顺序都可以(指superman内裤反穿???)。

public class DMain {
	public static void apart() {
		System.out.println("\n----------------------------------------------------------\n");
	}
	public static void main(String[] args) {
		A tmp1 = new concreteA();//基础的实现
		tmp1.print();
		apart();
		
		A tmp2 = new dA(new concreteA());//包装了dA特性
		tmp2.print();
		apart();
		
		A tmp3 = new dB(new concreteA());//包装了dB特性
		tmp3.print();
		apart();
		
		A tmp4 = new dA(new dB(new concreteA()));//同时包装了dB,dA特性
		tmp4.print();
	}
}

让我们看看它的输出

concrete A

----------------------------------------------------------

concrete A
dA

----------------------------------------------------------

concrete A
dB

----------------------------------------------------------

concrete A
dB
dA

仓促之间,如有错误欢迎指出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值