装饰者模式

本文介绍了装饰者模式的设计原理及其在实际开发中的应用。通过具体的Java代码示例,展示了如何利用装饰者模式对类的功能进行动态扩展,同时遵循面向接口编程的原则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设计模式本质上就是“SOLID设计原则”在实际应用中的具体体现,我们在实际开发中要尽量面向抽象编程、面向接口编程。顾客->菜单<-厨师,顾客面向菜单点菜,厨师面向菜单做菜,顾客点的菜必须在菜单范围内,厨师能做的菜也必须在菜单范围内,菜单即接口,这就是面向接口编程思想,做项目的时候,先定义接口,再定义实现接口的类,才算是面向抽象编程、面向接口编程。

装饰者模式的作用:能够在不修改目标类也不使用继承的情况下,动态地对类进行扩展,它是通过创建一个包装对象(装饰者)来达到增强目标类的目的。

装饰者模式的实现有两个要求:
1、装饰者类与目标类要实现相同的接口,或继成自同一类
2、装饰者类中要有目标类的引用作为成员变量,实际赋值一般通过带参构造器完成

第一步:基本装饰者模式

本例中只能对目标类进行单一装饰,核心部分是通过带参构造方法把目标类传到装饰者类当中,然后在装饰者类中对目标类进行装饰(即增强)。

程序结构图如下:

public interface ISomeService {
	public String doSome();
}
public class SomeService implements ISomeService {
	@Override
	public String doSome() {
		return "abcabc";
	}
}
public class SomeServiceDecorator implements ISomeService {
	private ISomeService target;
	
	public SomeServiceDecorator() {}

	public SomeServiceDecorator(ISomeService target) {
		this.target = target;
	}

	@Override
	public String doSome() {		
		return target.doSome().toUpperCase();
	}
}
public class MyTest {
	public static void main(String[] args) {
		ISomeService target = new SomeService();
		ISomeService decorator = new SomeServiceDecorator(target);
		System.out.println(decorator.doSome());
	}
}

第二步:装饰者链

本例中可以对目标类进行多种装饰,核心部分是通过带参构造方法把目标类传到装饰者类当中,然后在装饰者类中对目标类进行装饰(即增强)。
之所以在这里能够形成装饰者链,是因为带参构造器中的参数是接口类型的,这样才能接收多种类型的目标类,这也算是体现了面向抽象编程、面向接口编程的好处吧。
第二步与第一步的主要区别是装饰者类的命名方式不同,如果单纯从代码的角度来考虑,第一步也可以实现链式装饰,但是第一步中的装饰者类名是“SomeServiceDecorator”,如果想实现链式装饰难道再建一个“SomeServiceDecorator2”?这显然不合适,“SomeServiceDecorator”表示对SomeService进行综合装饰,就不应该再出现其他装饰者;如果想对目标类进行逐步装饰的话,就应该使用第二步的命名方式,用具体的装饰功能进行命名,这样才更符合OOP思想,也更具有可读性。
不同的命名方式体现了不同的设计思想,现在我对这一理念有了更丰富的理解。

程序结构图如下:


public interface ISomeService {
	public String doSome();
}
public class SomeService implements ISomeService {
	@Override
	public String doSome() {
		return "abcabc";
	}
}
public class ToUpperDecorator implements ISomeService {
	private ISomeService target;
	
	public ToUpperDecorator() {}

	public ToUpperDecorator(ISomeService target) {
		this.target = target;
	}

	@Override
	public String doSome() {		
		return target.doSome().toUpperCase();
	}
}
public class ReplaceDecorator implements ISomeService {
	private ISomeService target;
	
	public ReplaceDecorator() {}

	public ReplaceDecorator(ISomeService target) {
		this.target = target;
	}
	
	@Override
	public String doSome() {
		return target.doSome().replace("A", "*");
	}
}
public class MyTest {
	public static void main(String[] args) {
		ISomeService target = new SomeService();
		ISomeService toUpper = new ToUpperDecorator(target);
		ISomeService replace = new ReplaceDecorator(toUpper);
		System.out.println(replace.doSome());
	}
}

第三步:进一步抽象

有没有发现ToUpperDecorator、ReplaceDecorator中都有一个ISomeService类型的target变量,这可是重复代码哇,为了构建稳定、高效、可维护的程序,我们应该尽量减少重复代码。在这里我们为这些装饰者建一个实现了ISomeService接口的父类SomeServiceWrapper,父类中有target变量,此时子类就不需要实现ISomeService了,直接继承SomeServiceWrapper即可。

注意装饰链的装饰顺序:
ISomeService replace = new ReplaceDecorator(toUpper);是把toUpper作为参数传到replace中,简化之后的执行顺序大概是这样的xxx.toUpper().replace(),因此是toUpper()先执行,replace()后执行。

public interface ISomeService {
	public String doSome();
}
public class SomeService implements ISomeService {
	@Override
	public String doSome() {
		return "abcabc";
	}
}
public class SomeServiceWrapper implements ISomeService {
	private ISomeService target;
	
	public SomeServiceWrapper() {}
	
	public SomeServiceWrapper(ISomeService target) {
		this.target = target;
	}

	@Override
	public String doSome() {
		return target.doSome();
	}
}
public class ToUpperDecorator extends SomeServiceWrapper {	
	public ToUpperDecorator() {}


	public ToUpperDecorator(ISomeService target) {
		super(target);
	}

	@Override
	public String doSome() {		
		return super.doSome().toUpperCase();
	}
}
public class ReplaceDecorator extends SomeServiceWrapper {
	public ReplaceDecorator() {}


	public ReplaceDecorator(ISomeService target) {
		super(target);
	}
	
	@Override
	public String doSome() {
		return super.doSome().replace("A", "*");
	}
}
public class MyTest {
	public static void main(String[] args) {
		ISomeService target = new SomeService();		
		ISomeService toUpper = new ToUpperDecorator(target);
		ISomeService replace = new ReplaceDecorator(toUpper);
		System.out.println(replace.doSome());
	}
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

changuncle

若恰好帮到您,请随心打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值