我如何处理一个购物篮,其中有很多产品的成本计算可能不同

阿巴西

我正在做一项任务,我至少有几个产品有问题,例如买一送一,买 4 送一,买 5 并获得 20% 的折扣。现在我想知道我应该怎么做来处理这样的问题,因为当我遇到更多的产品时,产品计算的代码库会失控。这里最好的解决方案是什么?目前我所做的是根据每个产品代码创建一个类,并且产品的计算在该文件中是本地的。对象构造是通过静态工厂方法完成的。关于算法改进的任何建议,如果我可以进一步减少代码并使其简单,那就太好了。

class BOGOFCalculator implements BasketPriceCalculator
{
    const MIN_ITEMS_REQUIRED_FOR_DISCOUNT = 2;

    /**
     * @param Product $product
     * @param integer $totalItems
     * @return float
     */
    public function calculate(Product $product, $totalItems): float
    {
        return $this->calculateFullPrice($product, $totalItems) - $this->calculateDiscount($product, $totalItems);
    }

    /**
     * @param Product $product
     * @param $totalItems
     * @return float
     */
    private function calculateFullPrice(Product $product, $totalItems): float
    {
        return $product->getPrice() * $totalItems;
    }

    /**
     * @param Product $product
     * @param $totalItems
     * @return float
     */
    private function calculateDiscount(Product $product, $totalItems): float
    {
        return $product->getPrice() * floor($totalItems/static::MIN_ITEMS_REQUIRED_FOR_DISCOUNT);
    }
}

篮子看起来像下面

class Basket
{
    /**
     * @param Product[] $products
     *
     * @return float
     */
    public function calculateProductTotal(Product ...$products): float
    {
        $totalItemsOfEachProduct = $this->getTotalItemsOfEachProductInTheBasket(...$products);
        $items = $this->getDistinctProductsInTheBasketWithQuantity(...$products);
        $total = 0;
        foreach ($items as $productCode => $item) {
            /** @var BasketPriceCalculator $priceCalculator */
            $priceCalculator = PriceCalculatorFactory::getInstance($productCode);
            $total += $priceCalculator->calculate($item, $totalItemsOfEachProduct[$productCode]);
        }

        return $total;
    }

    /**
     * @param Product[] $products
     *
     * @return array
     */
    private function getTotalItemsOfEachProductInTheBasket(Product ...$products): array
    {
        $totalItemsPerProductCode = array_map(function ($product) { return $product->getCode(); }, $products);

        return array_count_values($totalItemsPerProductCode);
    }

    /**
     * @param Product[] $products
     *
     * @return array
     */
    private function getDistinctProductsInTheBasketWithQuantity(Product ...$products): array
    {
        $items = [];
        foreach ($products as $product) {

            if (!array_key_exists($product->getCode(), $items)) {
                $items[$product->getCode()] = $product;
            }
        }

        return $items;
    }
}
毛圈

在我看来,这里有两个独立的概念:打折产品(例如 -30% 没有自定义条件)和交易这意味着,您的购物篮包含产品集合和交易集合

每次“处理”篮子(调用它getTotalPrice()listProducts()或者getTotalSaving()您将交易应用于产品。“处理”不应影响篮子的内部产品集合,而只会影响返回的集合/结果。

每笔交易都包含两个方面:条件(或规则)和奖励您将使用该规则来确定是否应将给定的交易添加到用户的购物篮中

public function addProduct($product)
{
    for ($this->deals as $deal) {
        if ($this->basket->willMatch($product, $deal) {
            $this->basket->addDeal($deal);
        }
    }
    $this->basket->addProduct($product);
}

当检查是否成交要添加的需求,你需要比较的“真实名单”的产品,已经是篮子里面,再加上“引入的项目”对规则一的交易

至于将任何交易添加篮子中,您只需要确保篮子内的所有交易都是唯一的。

当您从购物篮中移除商品时,购物篮应重新检查所有交易的规则是否仍然匹配并丢弃过时的规则。

当您请求从用户的篮子中列出 *products 时,您应用所有交易奖励函数,其中每个交易返回一个的产品列表,而不会影响篮子的“真实列表”。

注意:这也意味着,您需要实际购买clone产品,否则您将无法使用奖励来应用折扣(因为否则,由于传递处理程序,折扣也将应用于“真实列表”项目行为)

这样,交易就可以应用而无需重新检查它们是否真正符合规则您只需运行奖励,例如,为每个充电器添加一根免费的 USB 电缆,并在listProducts()结果中添加 2 根电缆

至于你如何具体定义交易,这取决于你。它们可以由您的销售 CMS 制作,也可以硬编码为不同的类,也可以混合使用。它并不真正影响上述方法。

更新

所以,我上面提到的条件“硬编码处理”的例子(关于充电器的那个):

namespace Market\Deal;
use Market\Repository\Product as Stock;
use Market\Entity\Product;
use Market\Entity\ProductCollection;

class ChargetExtras implements Applicable 
{
    private $repository;

    public function __construct(Stock $repsoitory)
    {
        $this->repository = $repository;
    }

    public function canApply(Product $next, ProductCollection $current): bool
    {
        $predicted = new ProductCollection;
        $predicted->copyFrom($current);
        $predicted->add($next);

        return $predicted->has(new Product(1515)) >= 2 && 
               $predicted->has(new Product(48)) >= 1;
        // here 1515 is ID for cables and 48 - for charger
    }


    public function apply(ProductCollection $current): ProductCollection
    {
        $next = new PdocutCollectionl
        $next->copyFrom($current);

        $count = min(
            (int) $current->has(new Product(1515))/2,
            $current->has(new Product(48))
        );

        // for each combination of 2 cables and 1 charger, add free cable
        while ($count--) {
            $gratis = $this->repository->get(1515);
            $gratis->setPrice(0);
            $next->add($gratis);
        }

        return $next;
    }
}

canApply()方法是规则,其用于检查,该交易是否可以被应用,并且奖赏包含在apply()方法。

你会打电话给他们无论是从内部Basket阶层,通过将产品的“真正的名单”。如您所见,这笔交易在任何时候都不会影响原始列表。它始终适用于副本。

而且,由于每笔交易中的逻辑相对简单,您可以创建一些“动态规则”类,该类使用在您的 CMS 中定义的条件。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

我有一个行表,其中有复选框。如何选择特定的复选框

使用 NewMailEx 处理一个帐户,其中有多个帐户

我有一个执行流程问题,其中有nodejs子进程

当我不知道其中有多少个文本框时,应该如何处理多个文本框?

如何在 Excel 中引用完整的列,其中有一个值

购物篮:带有选件的产品,如何检查是否存在组合?

python:我有一个列表,其中有逗号分隔的元素,我想获得唯一的元素

如何让 Excel 从右到左读取并找到第一个案例,其中有一个“X”

我有一个Excel文件。在其中有多个列和行的情况下,如何根据ggplot的行过滤列

将数量添加到购物篮中将添加一个新商品

如果商品“有货”,我如何告诉 selenium 添加到购物篮?

如何查找此数组是否有重复的对象,其中有另一个数组

Excel如何将筛选器应用于其中有一个值的列?

我有一个数据表,其中有一个带有十进制值的列

Javascript返回一个空数组,但其中有两个元素

计算最便宜的购物篮

发布一个实体与Spring数据REST其中有关系

防止用户选择日期范围,其中有一个禁用的日期之间

当其中有一个按钮时,使div背景可点击

我有一个 alertDialog,其中有复选框。我想保留用户签入的复选框的值

选择一个div内的第一个div,但前提是其中有10个

如何调用其中有一个自定义的复杂对象类型作为从Java输入参数一个Oracle PL-SQL过程

我们怎么可以拆分数据输入,其中有些是由一个空间,部分有2空格分开?

父 div,有两个孩子,其中有确切的高度,如何给另一个孩子“自由左”空间作为高度

当Woocommerce中购物篮中有商品时,添加自定义主体类

如何更新购物篮并更改多维数组中的产品数量?

求一个N ^ 2个数字的中位数,其中有N个记忆

如何在 javascript 中随机播放两个对象,其中有一个 Id 和值

我需要一个应用程序屏幕,其中有一个图标网格(可点击)、一个横幅和一个项目列表视图