【问题标题】:Java - Visitor pattern for adding methodsJava - 添加方法的访问者模式
【发布时间】:2016-10-05 20:54:39
【问题描述】:

所以我为液体创建了一个简单的访客模式。如牛奶、果汁和白酒。

Milk 类可以如下所示:

public class Milk implements Visitable{

public float tax=0;

@Override
public int price() {
    return 4;
}

@Override
public void accept(Visitor visitor) {
    visitor.visit(this);
}
}

//果汁和酒类也是如此

然后我们可以让一个看起来像这样的访问者来完成计算税金的工作:

public class TaxVisitor implements Visitor {

double taxPerentLiquor=.18;
double taxPerentMilk=.15;
double taxPerentJuice=.10;


@Override
public void visit(Liquor liquor) {

    int price =liquor.price();
    liquor.setTax((float) (price*taxPerentLiquor));
}

@Override
public void visit(Milk milk) {
    float price =milk.price();
    milk.setTax((float) (price*taxPerentMilk));


}

@Override
public void visit(Juice juice) {

    int price =juice.price();
    juice.setTax((float) (price*taxPerentJuice));

}

}

当我们使用它时,我们会这样做:

Visitor taxVisitor = new TaxVisitor();

    Milk milk = new Milk();
    Juice juice = new Juice();

    milk.accept(taxVisitor);
    juice.accept(taxVisitor);

“访客”会为我计算每种液体的税金。我看到了当我想添加新计算时我不必修改对象集合本身的好处。但是当我想添加一个新方法时,我的麻烦就来了。例如,遵循开放封闭原则,我不应该向牛奶类添加新方法。但是让我们想象一下,我想添加功能以了解液体是什么颜色。所以我想扩展牛奶对象以拥有一个名为“getColor()”的方法,该方法将返回“#FFFFFF”。如果我想遵循 SOLID 开放封闭原则,这似乎需要一个装饰器模式来添加此功能。有没有办法通过访问者模式做到这一点?

【问题讨论】:

  • 除非您打算存储访问者中每种液体的颜色(就像您对税收所做的那样),否则不会。访问者不会向对象添加行为,它会在对象上执行行为。与您的税务访问者一样,您不会向对象添加行为,您只是根据对象的类型执行行为(这可能会触发对象执行已经存在的行为)
  • 我明白了。所以访问者是为了执行行为而不是添加行为。
  • 从技术上讲,它确实会添加行为,但不会添加到元素中。这些行为属于元素的,而不仅仅是一个元素。将其应用于您的情况的问题由您的TaxVisitor 表达:访问者需要维护元素未维护的任何状态。因此,如果没有一种液体保持自己的颜色,ColorVisitor 将不得不保持所有这些液体。这是可能的,但不切实际。
  • 如果我想在我的元素集合中添加方法(添加元素行为)而不修改它们,你推荐什么模式?
  • 在您的液体中添加getColor()违反 O/C。这就是“open for extension”的目的:您仍然可以添加行为,只要它们不影响任何现有行为。如果您影响现有代码,任何依赖于它的代码也可能受到影响,这可能会破坏合约(从而破坏软件)。如果添加getColor() 不会影响任何工作代码,那么这不是违反原则,而是扩大规模。 Look at the first bullet point from this link

标签: java design-patterns visitor-pattern open-closed-principle


【解决方案1】:

添加函数,你没有违反O/C

添加新函数不会违反 O/C,只要该函数不影响任何现有代码即可。将getColor() 添加到您的液体中会非常好。

O/C 是关于防止修改现有代码

O/C 的目的是避免违反合同。当开发人员编写软件时,他们会准确地指定软件应该如何工作和不应该如何工作。这是合同。

在编写其他开发人员所依赖的代码时,您无法确定这些开发人员制定了哪些合同。您所知道的只是您为代码定义的合同。开发人员相信您不会以修改他们的方式修改您的合同。

由于您无法确定更改合约是否会影响其他开发者的合约,因此其他开发者使用的您的任何代码都必须“CLOSED以进行修改”,或者你冒着违反合同的风险。

O/C 不会阻止您扩大规模

添加对现有代码没有影响的代码不会承担干扰其他开发人员合同的风险。

如果你添加一些功能,没有人会强迫客户在他们的系统中使用这些新功能;如果它们不会被使用,它们不需要担心任何潜在的风险,或者它们甚至是如何工作的。类是“OPEN for extension”,因为它不会对现有客户造成任何潜在伤害。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-18
    • 2010-11-02
    • 1970-01-01
    • 2022-12-04
    • 1970-01-01
    相关资源
    最近更新 更多