在java中使用Decorator设计模式的问题

时间:2017-10-07 17:31:55

标签: java design-patterns

我想在这里使用装饰模式。 BaseCart是抽象类。购物车扩展了BaseCart并获得总价。现在我想在不改变现有代码的情况下给出购物车总价值的折扣。所以我创建了CartDecorator,它扩展了BaseCart,然后创建了TotalDiscountCart,它将获得总金额,然后对其应用折扣。

现在我正在尝试运行下面给出的单元测试没有给出正确的输出。产品添加到购物车中但是当调用Cart的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());
    }

1 个答案:

答案 0 :(得分:1)

您应该将addProduct委托给cart中的CartDecorator。创建Cart接口可能也是有意义的,因为CartDecorator不会从子类BaseCart中获利。

  

请你详细说明'创建购物车界面,因为CartDecorator不会从子类化BaseCart中获利。'?

你的BaseCart实际上做了两件事。一个是定义使用推车的界面(由addProductgetTotalPrice方法组成)。另一个是为addProduct提供填充productsWithQuantity地图的基本实现。

现在CartDecorator装饰另一辆车。它(当然)应该实现与所有购物车相同的界面。但对于CartDecorator而言,从addProduct继承BaseCart实施方式实际上会适得其反。因为CartDecorator可以将addProduct委托给装饰的购物车 - 所以它实际上不需要自己的productsWithQuantity地图等。

这就是为什么定义Cart接口可能是有意义的,如果您认为需要它,则需要一个基本的抽象实现,如BaseCartCartDecorator然后会实现Cart接口,但不会扩展BaseCart