结构类模式:代理模式VS装饰模式。

本文对比分析了代理模式和装饰模式,详细解释了两者在功能控制与功能增强上的区别,通过具体实例展示了如何在不改变接口的情况下,利用代理模式控制行为的发生,以及如何使用装饰模式增强类的功能。

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

对于两个模式,首先要说的是,装饰模式就是代理模式的一个特殊应用,两者的共同点是都具有相同的接口,不同点则是代理模式着重对代理过程的控制,而装饰模式则是对类的功能进行加强或减弱,他着重类的功能变化,我们举例来说明他们的区别。

代理模式

一个著名的短跑运动员有自己的代理人。如果你很仰慕他,你找运动员说“你跑个我看看”,运动员肯定不搭理你,不过你找到他的代理人就不一样了,你可能和代理人比较熟,可以称兄道弟,这个忙代理人还是可以帮的,于是代理人同意让你信商运动员的练习赛,这对你来说已经是莫大荣耀了。

这是一个套用代理模式的简单应用,非常简单!一个对象,然后再是自己的代理。我们先来看一下代理,先看抽象主题类,如下所示。

public interface IRunner {
	/**
	 * 运动员的主要工作就是跑步
	 */
	void run();
}

一个具体的短跑运动员跑步是很潇洒地,如下所示。

public class Runner implements IRunner {

	@Override
	public void run() {
		System.out.println("运动员跑步:动作很潇洒");
	}

}

看看现在的明星运动员,一般都有自己的代理人,要么是专职的,要么就是自己的教练兼职,那我们来看看代理人的职责,如下所示。

public class RunnerAgent implements IRunner {
	private IRunner runner;

	public RunnerAgent(IRunner runner) {
		this.runner = runner;
	}

	@Override
	public void run() {
		Random random = new Random();
		if (random.nextBoolean()) {
			System.out.println("代理人同意安排运动员跑步");
			this.runner.run();
		} else {
			System.out.println("代理人心情不好,不安排运动员跑步");
		}
	}

}

我们只是定义了一个代理人,并没有明确定义是哪一个运动员的代理,需要在运行时指定被代理者,而且我们还在代理人的run方法中做了判断,想让被代理人跑步就跑步,不乐意就拒绝,对于主题类的行为是否可以发生,代理类有绝对的控制权。我们编写一个场景类来模拟这种情况,如下所示。

public class Client {
	public static void main(String[] args) {
		// 定义一个短跑运动员
		IRunner liu = new Runner();
		// 定义提liu的代理人
		IRunner agent = new RunnerAgent(liu);
		// 要求运动员跑步
		System.out.println("====客人找到运动员的代理要求其去跑步====");
		agent.run();
	}
}

不管是哪种情况,我们都证实了代理的一个功能:在不改变接口的前提下,对过程进行控制。在我们例子中,运动员要不要跑步是由代理人决定的,代理人说跑步就跑步,说不跑就不跑,他有绝对判断权。

装饰模式

如果使用装饰模式,我们该怎么实现这个过程呢?装饰模式是对类功能的加强,怎么加强呢?增强跑步速度!在屁股后面安装一个喷气动力装置,类似火箭的喷气装置,那速度变得很快,《蜘蛛侠》中的那个反面角色不就是这样的吗?

我们来看代码,IRunner和Runner与代理模式相同,在此不再赘述。我们来看装饰类RunnerWithJet,如下所示。

public class RunnerWithJet implements IRunner {
	private IRunner runner;
	public RunnerWithJet(IRunner runner) {
		this.runner = runner;
	}
	@Override
	public void run() {
		System.out.println("加快运动员的速度:为运动员增加喷气装置");
		this.runner.run();
	}

}

这和代理模式中的代理类也是非常相似的,只是装饰类对类的行为没有决定权,只有增强作用,也就是说他不决定被代理的方法是否执行,他只是再次增加被代理的功能。我们来看场景类,如下所示。

注意思考一下我们的程序,我们通过增加了一个装饰类,就完成了对原有类的功能增加,由一个普通的短跑运动员变成了带有喷气装置的超人运动员,其速度岂是普通人能相比的!

最佳实践

通过例子,我们可以看出代理模式和装饰模式有非常相似的地方,甚至代码实现都非常相似,特别是装饰模式中省略抽象装饰角色后,两者代码基本上相同,但是还是有细微的差别。

代理模式是把当前的行为或功能委托给其他对象执行,代理类负责接口限定:是否可以调用真实角色,以及是否对发送到真实角色的消息进行变形处理,他不对被主题角色(也就是被代理类)的功能做任何处理,保证原汁原味的调用。代理模式使用到极致开发就是AOP,这是各位采用Spring架构开发必然要使用到的技术,他就是使用了代理和反射的技术。

装饰模式是在要保证接口不变的情况下加强类的功能,他保证的是被修饰的对象功能比原始对象丰富(当然,也可以减弱),但不做准入条件判断和准入参数过滤,如是否可以执行类的功能,这不是装饰模式关心的。

代理模式在Java的开发中俯拾皆是,是大家非常熟悉的模式,应用非常广泛,而装饰模式是一个比较拘谨的模式,在实际应用中接触比较少,但是也有不少框架项目使用了装饰模式,例如在JDK的java.io.*包中就大量使用装饰模式,类似如下的代码:

OutputStream out = new DataOutputStream(new FileOutputStream("test.txt"));

这是装饰模式的一个典型应用,使用DataOutputStream封装了一个FileOutputStream,以方便进行输出流处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值