首页app攻略深入理解Java虚拟机第三版电子版 深入理解java的栈与堆

深入理解Java虚拟机第三版电子版 深入理解java的栈与堆

圆圆2025-08-02 10:01:10次浏览条评论

深入理解java装饰者模式与内部方法调用:一种设计考量本文旨在探讨Java装饰器模式中,被装饰对象内部方法调用行为的特性,以及如何处理“辅助方法”不被装饰器影响的问题。我们将分析装饰器模式的工作原理,解释为什么内部这个调用无法被外部装饰器感知,并提供两种不同的设计策略:一种是严格遵循装饰器模式进行外部增强,另一种是利用继承实现内部行为的行为模式,并明确区分这两种适用场景。 理解装饰者模式与内部方法调用的挑战

装饰者模式(Decorator) Pattern)是一种允许结构型设计模式,它在不改变原有对象结构的情况下,动态地给对象添加新的功能。它通过将对象包装在一个装饰器对象中来实现,装饰器与被装饰对象实现相同的接口,从而使得客户端代码可以透明地使用装饰过的对象。

然而,当被装饰对象内部的方法(例如,一个“辅助方法”)通过这个关键字调用其自身类的其他方法时,这些内部部分调用将指向被装饰对象本身的实现,而不会被外部的装饰器所拦截或修改。这正是问题中遇到的挑战:flagImpl.wave()内部调用this.calculateWind()时,即使存在一个decoratedFlag,flagImpl的calculateWind()方法仍然会被调用,而不是decoratedFlag中可能存在的同名方法。

让我们通过一个简化的Java代码示例来具体说明这个问题:// 1. 组件接口(Component Interface)公共接口 Flag { int wave(); intcalculateWind();}// 2. 具体组件(具体组件)public class FlagImpl Implements Flag { @Override public int wave() { System.out.println(quot;FlagImpl: Waving. 内部风计算结果: quot;calculateWind()); returncalculateWind(); // 内部调用FlagImpl自身的calculateWind() } @Override public intcalculateWind() { System.out.println(quot;FlagImpl:执行基础风计算。quot;); return 8; }}// 3. 抽象装饰器(Abstract Decorator)//修改了原始问题中装饰器方法的错误调用public abstract class FlagDecorator Implements Flag { protected Flagdecorator Implements Flag { protected Flagdecoratorimplements Flag; // 持有被装饰对象的引用 public FlagDecorator(FlagdecoratedFlag) { this.decoratedFlag =decoratedFlag; } @Override public int wave() { // 默认行为:委托给被装饰对象 returndecoratedFlag.wave(); } @Override public intcalculateWind() { // 默认行为:委托给被装饰对象 returndecoratedFlag.calculateWind(); }}// 4.具体装饰器(ConcreteDecorator)public classEnhancedFlagDecorator extends FlagDecorator { public EnhancedFlagDecorator(FlagdecoratedFlag) { super(decoratedFlag); } @Override public int wave() { System.out.println(quot;EnhancedFlagDecorator:添加预波动作.quot;); int result =decoratedFlag.wave(); // 委托给被装饰对象的wave() 方

法 System.out.println(quot;EnhancedFlagDecorator:添加波后动作。quot;); return result 10; // 行为增强 } @Override public intcalculateWind() { System.out.println(quot;EnhancedFlagDecorator:修改风计算。quot;); // 委托给被装饰对象的calculateWind()并进行 returndecoratedFlag.calculateWind() 5; }}登录后复制

运行示例及分析:

立即学习“Java免费学习笔记(深入)”;public class DecoratorDemo { public static void main(String[] args) { Flag flag = newEnhancedFlagDecorator(new FlagImpl()); System.out.println(quot;wave()结果: quot; flag.wave()); System.out.println(quot;---quot;); System.out.println(quot;直接calculateWind()的结果: quot; flag.calculateWind()); }}登录后复制

输出:EnhancedFlagDecorator:添加预挥动动作。FlagImpl:挥动。内部风计算结果: 8FlagImpl:执行基础风计算。EnhancedFlagDecorator:添加波后动作。wave()结果: 18---EnhancedFlagDecorator:修改风计算。FlagImpl:执行基础风计算。直接calculateWind()结果: 13登录后复制

从输出中可以看出,当调用flag.wave()时,EnhancedFlagDecorator.wave()被调用,它委托给FlagImpl.wave()。而FlagImpl.wave()内部的calculateWind()调用,始终是FlagImpl本身的calculateWind(),而不是EnhancedFlagDecorator的calculateWind()。这就是装饰者模式的特性:它在外部包装和增强行为,但不会改变被装饰对象内部的this引用和方法分派逻辑。

2.解决“辅助方法”不被装饰器影响的问题

针对上述问题,根据你的设计意图,可以采取不同的策略。2.1 策略一:严格遵循装饰器模式,明确职责边界

如果希望calculateWind()方法能够被装饰器影响,那么它就不应该FlagImpl内部的“辅助方法”,而应该被视为Flag接口的一部分,且其行为是外部可观察和可修改的。在这种情况下,FlagImpl.wave()不应直接调用this.calculateWind(),而是通过其外部接口调用。

然而,这通常意味着wave()方法本身也应该通过外部接口调用calculateWind(),或者calculateWind()不应该是wave()的内部依赖,而是外部可以独立调用的功能。

注意事项:装饰者模式主要用于在运行时为对象添加外部它不会改变被装饰对象内部方法调用的行为。如果一个方法内部调用了另一个方法,并且你希望这个内部调用的目标方法能被装饰器影响,那么装饰器模式可能不是最直接的解决方案,或者需要重新设计接口和职责。2.2 策略二:利用继承实现内部行为的修改(非装饰者模式)

如果你的核心需求是做一个类(如FlagImpl)的某个方法(如wave())能够调用其子类中重写的“辅助方法”(如calculateWind()),那么这实际上是面向对象编程中多状态和继承的典型应用,而不是装饰器模式。

在这种场景下,你可以将FlagImpl设计为一个抽象基类或具体基类,并让其方法(如wave())调用另一个可以子类重写的方法(如calculateWind())。子类通过重写这些方法来改变其行为。

以下是基于继承的解决方案,它与原问题答案的思路一致(虽然原答案使用了C#语法,但核心思想是相通的):// 1. 抽象基类(Abstract Base Class)//包含可被子类重写的方法 public abstract class AbstractFlag { public intcalculateWind() { System.out.println(quot;AbstractFlag:执行基风计算.quot;); return 8:可以不重写任何方法,直接使用父类实现}// 3.扩展类(Extended Class) - 模拟“装饰”行为,但通过继承实现公共类ExtendedFlag extends AbstractFlag { @Override public int wave() { System.out.println(quot;ExtendedFlag: 添加前波动作。quot;); int result = super.wave() 100; // 调用父类的 wave() 方法 System.out.println(quot;ExtendedFlag: 添加后波动作。quot;); return result; } @Override public intcalculateWind() { System.out.println(quot;ExtendedFlag:修改风计算。quot;); return super.calculateWind() 300; // 调用父类的calculateWind()方法并增强 }}登录后复制

运行示例及分析:

学习立即“Java免费学习笔记(深入)”;public class InheritanceDemo { public static void main(String[] args) { AbstractFlag flag = new ExtendedFlag(); System.out.println(quot;结果

lt of wave(): quot; flag.wave()); System.out.println(quot;---quot;); System.out.println(quot;直接calculateWind()的结果: quot; flag.calculateWind()); }}登录后复制

输出:ExtendedFlag: 添加预挥动动作。当前实例计算的风: 308ExtendedFlag: 修改风计算。AbstractFlag: 执行基础风计算。ExtendedFlag: 添加波后动作。wave()结果: 408---ExtendedFlag: 修改风计算。AbstractFlag: 执行基础风计算。直接calculateWind()的结果: 308登录后复制

在这个继承的例子中,当调用ExtendedFlag.wave()时,它会调用super.wave(),进一步调用AbstractFlag.wave()。在AbstractFlag.wave()内部,this.cal culateWind()的调用会ExtendedFlag重写了calculateWind()方法而**多态性分

以上就是因为深入理解Java装饰者模式与内部方法调用:一个设计考量的详细内容,更多请关注乐哥常识文章相关!

深入理解Java装饰
英雄联盟手游峡谷超卖会 英雄联盟手游61什么时候更新
相关内容
发表评论

游客 回复需填写必要信息