我试图在这里使用装饰器模式。 BaseCart是抽象类。购物车扩展了BaseCart并获得总价。现在,我想在不更改现有代码的情况下为购物车总价值提供折扣。因此,我创建了扩展BaseCart的CartDecorator,然后创建了TotalDiscountCart,它将获取总金额,然后对其应用折扣。

现在,我尝试运行以下给出的单元测试,但未给出正确的输出。产品已添加到购物车中,但是当调用购物车的getTotalPrice()方法时,productsWithQuantity为空。
它不应该添加值吗?为什么它是空的以及如何解决呢?

    public abstract class BaseCart {


        Map<Product, Integer> productsWithQuantity = new HashMap<Product, Integer>();
        Double totalPrice = 0.0;

        public void addProduct(Product product, Integer quantity){
            productsWithQuantity.put(product, quantity);
        }

        public abstract Double getTotalPrice();
    }


    public class Cart extends BaseCart{

        @Override
        public Double getTotalPrice() {
            productsWithQuantity.forEach((product ,quantity )-> totalPrice = totalPrice + product.getUnitPrice() * quantity);
            return totalPrice;
        }


    }


public class CartDecorator extends BaseCart{

    BaseCart cart;

    public CartDecorator(BaseCart cart) {
        super();
        this.cart = cart;
    }

    @Override
    public Double getTotalPrice() {
        return this.cart.getTotalPrice();
    }

}

public class TotalDiscountCart extends CartDecorator{

    public TotalDiscountCart(BaseCart cart) {
        super(cart);
    }

    @Override
    public Double getTotalPrice() {
        super.getTotalPrice();
        return totalPrice - (percentDiscount(10.0));

    }

    private Double percentDiscount(Double i) {
        return 0.1 * totalPrice;
    }


}

    @Test
    public void shouldGiveDiscountOf9() {
        //Given
        BaseCart cart = new TotalDiscountCart(new Cart());

        Product productDove = new Product("Dove soap", 30.0);

        //when
        cart.addProduct(productDove, 3);

        // then
        assertEquals(Double.valueOf(81.0),cart.getTotalPrice());
    }

最佳答案

您应该将addProduct委派给cart中的CartDecorator。创建Cart接口可能也很有意义,因为CartDecorator不能从子类BaseCart中受益。


  您能否详细说明一下“创建Cart界面,因为CartDecorator不会从BaseCart的子类化中获利”?


您的BaseCart实际上做了两件事。一种是定义一个与购物车一起使用的接口(由addProductgetTotalPrice方法组成)。另一个是addProduct的基本实现,它填充了productsWithQuantity映射。

现在,CartDecorator装饰另一个购物车。 (当然)它应该实现与所有购物车相同的接口。但是对于CartDecorator,从addProduct继承BaseCart实现实际上是适得其反的。因为CartDecorator可以将addProduct委派给装饰好的购物车-因此它实际上不需要自己的productsWithQuantity映射等。

这就是为什么定义Cart接口可能有意义的原因,并且如果您认为需要它,则可以使用诸如BaseCart之类的基本抽象实现。然后,CartDecorator将实现Cart接口,但不扩展BaseCart

10-07 20:36