【问题标题】:Overriding an internal method with Decorator Design Pattern使用装饰器设计模式覆盖内部方法
【发布时间】:2019-10-28 18:30:48
【问题描述】:

我正在编写一个面向对象的代码,我在其中尝试使用装饰器模式来实现各种优化,以便在运行时应用于一系列核心类。核心类的主要行为是在这些类中完全实现的复杂行为,它确实调用了其他内部方法来完成任务。 装饰器只会自定义核心类中复杂行为调用的内部方法。

这是我想要达到的伪代码:

interface I{
  complex();
  step1();
  step2();
}
class C implements I{
  complex(){
    ...
    this.step1();
    ...
    this.step2();
  }
  step1(){
    ...
  }
  step2(){
    ...
  }
}
abstract class Decorator implements I{
  I wrapped;
  constructor(I obj){
    this.wrapped = obj;
  }
  complex(){
    this.wrapped.complex();
  }
  step1(){
    this.wrapped.step1();
  }
  step2(){
    this.wrapped.step2();
  }
}
class ConcreteDecorator extends Decorator{
  constructor(I obj){
    super(obj);
  }
  step2(){
    ... // customizing step2()
  }
}

有多种自定义可以组合在一起,这就是我使用装饰器模式的主要原因。否则,我将为每种可能的自定义组合创建数十到数百个子类型。

现在,如果我尝试创建装饰类的对象:

x = new C();
y = new ConcreteDecorator(x);
y.complex();

我希望 complex() 方法从包装的核心对象中执行,同时使用装饰器中覆盖的 step2() 方法。但它不能这样工作,因为抽象装饰器中的 complex() 方法直接调用核心对象上的方法,确实跳过了装饰器中覆盖的step2()

我的总体目标是使装饰器仅覆盖stepx() 方法中的一个或几个,并且将由已在核心对象中实现并调用所有步骤的complex() 方法调用。

这个功能完全可以使用装饰器设计模式来实现吗?如果是,如何,如果不是,解决此问题的适当设计模式是什么。

谢谢。

【问题讨论】:

  • 步骤方法真的需要成为接口的一部分,即公开吗?
  • @Derefacto 是的! complex() 是类的主要行为。但是为了能够自定义行为的不同部分,我创建了那些较小的 step() 方法,其中任何一个都可以被子类/装饰器覆盖。

标签: oop design-patterns decorator


【解决方案1】:

我想你可以用策略模式解决这个问题,其中策略接口包含因类而异的方法。策略接口可能仅包含一种方法,也可能包含多种方法,具体取决于它们的性质。

interface IStrategy {
  step1(IData data);
  step2(IData data);
}

interface I {
  complex();
}

class C implements I {
  IData data

  constructor(IStrategy strategy) {}

  complex() {
    ...
    this.strategy.step1(this.data);
    ...
    this.strategy.step2(this.data);
  }
}

class S1 implements IStrategy {
  constructor(IStrategy strategy)

  step1(IData data) {
  }

  step2(IData data) {
  }
}

strategy1 = new S1();
c = new C(strategy1)

【讨论】:

  • 感谢您的回答。这是解决问题的合理方法,尽管它错过了装饰器模式的分层属性,您可以在核心类周围组合多个包装器。不管怎么说,还是要谢谢你。我最终决定实现责任链模式,将中间件类链接起来,形成与我希望通过装饰器模式实现的效果相同的效果。
  • 看到您的解决方案会很有趣。您可以将其添加到您的问题中吗?
【解决方案2】:

您面临的问题是,在您的装饰器设计模式的应用程序中,因为您没有装饰complex(),所以对装饰器对象的complex() 的调用将委托给装饰对象,该对象具有“正常" step2 的版本。

我认为更适合解决您的问题的设计模式是Template Method 设计模式。

在您的情况下,complex() 将扮演 模板方法 的角色,其步骤可以由子类自定义。您不使用组合,而是使用继承,其余部分或多或少保持不变。

以下是模板方法设计模式在您的上下文中的示例应用:

public interface I {
    void complex();
    void step1(); // Better to remove from the interface if possible
    void step2(); // Better to remove from the interface if possible
}

// Does not need to be abstract, but can be
class DefaultBehavior implements I {

    // Note how this is final to avoid having subclass
    // change the algorithm.
    public final void complex() {
        this.step1();
        this.step2();
    }

    public void step1() { // Default step 1
        System.out.println("Default step 1");
    }

    public void step2() { // Default step 2
        System.out.println("Default step 1");
    }
}

class CustomizedStep2 extends DefaultBehavior {

    public void step2() { // Customized step 2
        System.out.println("Customized step 2");
    }
}

【讨论】:

  • 感谢您的回答。使用装饰器模式的要点是我有多个可以以不同方式组合的自定义。所以使用你建议的模板方法意味着我必须定义几十个子类,这不是理想的情况。我更倾向于使用动态绑定模式来避免为每个可能的装饰器/自定义组合定义子类型。
猜你喜欢
  • 2020-05-13
  • 1970-01-01
  • 2021-10-04
  • 2011-09-07
  • 2012-04-23
  • 2010-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多