双向OOP设计模式

时间:2016-10-26 09:19:01

标签: oop design-patterns

这是一个普遍的问题,让我在特定场景中制定它。我正在编制定价系统。一方面,有几个“引擎”,另一方面有几个“工具”。我为它们创建了类层次结构。

我现在的问题是我要实施定价机制。给定特定的引擎和特定的工具,他们一起确定计算价格的算法。在2条目表中编码它会很好。这两个实例都包含重要信息,没有一个比另一个更重要。在OOP方法属于一个类,所以我认为没有像样的设计来处理这个:“定价”方法应该在Instruments类中,还是引擎?

无论我走哪条路,我都有同样的问题。假设我决定它应该在引擎中。然后,在定价方法中,我应该有一个'if-then-else'指令来处理每个可能的InstrumentClass?这看起来太难看了(紧耦合!),特别是如果我要用类似

之类的东西检查它
isinstance(inst, InstrClass1)

我可以想象在许多情况下会出现类似的情况。处理它们的最佳设计模式是什么?

REPHRASED as Vehicle + Circuit示例

假设您一方面拥有车辆的等级层次结构。摩托车,汽车等都是特定的对象 可能是Yahama Ray,它是摩托车的一个例子,也是一辆车。

另一方面,你有Circuits。 LeMans,Jerez,LagunaSeca等课程

我们想要做的是模拟给定电路中给定车辆的性能。例如,假设 输出是车辆完成一圈所需的时间。对于摩托车和汽车,物理学是不同的, 所以你有不同的算法。但也有人认为在某些电路中你需要考虑一些因素 在其他方面是无关紧要的。因此,只有当您了解车辆和电路的所有细节时,才能进行模拟。 你不能要求赛道“模拟自己”并获得时间,然后要求车辆“模拟自己”并给出 再过一次,最后用这两个人做出最后的答案。

希望这能说明我想要做的事情。

3 个答案:

答案 0 :(得分:2)

是否可以让CalculatorService具有接收引擎和仪器的方法。它可以包含将巩固发动机价格和仪器价格的逻辑。单个价格将来自Engine和仪器对象,因此封装不会被破坏。

class CalculatorService {
   public BigDecimal calculatePrice(Instrument instrument, Engine engine) {
    def instrumentPrice = instrument.calculatePrice()
    def enginePrice = engine.calculatePrice() 
    //algorithm to consolidate both prices.
   return consolidatedPrice
  }
}

答案 1 :(得分:1)

此问题没有通用答案,因为解决方案始终是特定于域的。

但是,作为一般准则,如果存在不适合任何现有对象的逻辑,那么您只是缺少一个额外的概念,这个概念通常表示为无状态服务,但并非总是如此。

例如,假设当15%Engine1一起购买时,Instrument1会有折扣。

显然,折扣逻辑不属于Engine1Instrument1,但你可能有一个Order,其中包含两个项目,订单可能有办法申请折扣。 Discount可以检查Order以了解他们的申请政策是否得到满足,并且可以返回特定订单的折扣金额。

class Order {
    ...

    public void applyApplicableDiscounts(List<Discount> discounts) {
        for (Discount discount : discounts) {
            if (discount.isApplicableTo(this)) {
                this.discounts.add(discount);
            }
        }
    }

    public Price netPrice() {
        return sumAllOrderLinePrices();
    }

    public Price totalPrice() {
        Money discountAmount = sumAllDiscountAmounts();

        return netPrice().deduct(discountAmount);
    }
}

class Engine1BoughtWithInstrument1Discount implements Discount {
    public boolean isApplicableTo(Order order) {
        return order.containProducts(/*Engine1, Instrument1*/);
    }

    public Money amountFor(Order order) {
        return order.netPrice().percentageOf(15);
    }
}

现在,对于车辆+电路示例,它是一样的。你可能会有一个有状态的Simulation或一个无状态的SimulationService,它可以运行一个模拟,给出一个车辆,电路,车辆,物理定律等等。这可能变得非常复杂,但基本上这些不同的合作者应该允许执行模拟的组件查询它们以收集执行模拟所需的详细信息。

不幸的是,我对这个领域和物理定律一无所知,但作为一个非常简单的例子(可能是愚蠢的),模拟服务可以查询电路以了解其中特定点的地形并询问车辆这是轮子的表面和形状,以了解会产生多少摩擦。

答案 2 :(得分:0)

我认为您需要第三种类型:定价,它使用Instrument的一个实例和一个Engine实例。定价类负责计算价格。