0

我应该首先说我是一个爱好程序员。当我从行医中休息时,我会(主要是)练习 PHP,并随着时间的推移尝试建立我的知识,同时希望在此过程中为人们解决一些问题。

最近,我一直在为我家的家装业务申请。该项目建立在 codeigniter 和 mongodb 之上,虽然它有效,但我知道它并不漂亮。我花了一些时间阅读有关设计模式的内容,并且很难确定哪个适合该项目的“估算器”部分。

以下是它的工作原理:

用户输入特定于确定价格的方法的一系列测量值。有时,这些测量值特定于一种产品类型 - 例如,排水沟。其他时候,测量与正在完成的工作比产品更密切相关 - 例如,用乙烯基和铝覆盖外部拱腹。

这就是说,每种特定的估计方法都需要不同类型的测量。继续上面的两个例子......

要估计排水沟,我们必须知道类型(小、大、屏幕)和线性英尺。重要的是要知道每种类型都有自己的价格。

要估计拱腹,我们必须只知道线性英尺。

估计方程相当简单 - 数量 x 价格 = 估计 - 但数量可以是件数、英尺数或平方英尺数。

我想知道我是否让这变得比它需要的更复杂,但我想把我的技能提升到一个新的水平,学习设计好的、面向对象的代码。该项目的下一步是进行这些测量并制定工作所需的材料清单 - 由于可用的产品数量众多,这项工作要复杂得多。

我应该考虑哪些设计模式?到目前为止,我主要看的是Abstract Factory. 应该Builder在我的名单上吗?还有什么?

4

1 回答 1

1

你能不能只创建一个“Estimator”接口,让它需要一个名为 Estimate() 的方法,然后用一组类扩展该接口,每个类都完成不同的估计。它们都有一个构造函数,它接受输入参数(估计所需的所有信息),它们都会隐含估计函数,该函数将输出总成本。

现在我知道你理解了这个模式,因为你列出了与它非常相似的模式。我只是想向你展示我是如何编写代码的,这样你就可以看到它是如何工作的。有时即使这听起来是个坏主意,但事实证明它工作得非常好,你只是无法想象它。

就像是:

interface Estimator
{
    public function Estimate ();
    public function BuildInfo ();
}

class Estimate_gutter implements Estimator
{
    private $totalLength, $gutterType;
    function __construct ($totalLength, $gutterType)
    {
        $this->totalLength = $totalLength;
        $this->gutterType = $gutterType;
    }

    function Estimate ()
    {
        return $this->totalLength * .45; // 45 cents a foot, consider a binary math library here though
    }

    function BuildInfo ()
    {
        return "Gutter Type: {$this->gutterType}, Length: {$this->totalLength}"; //to keep different classes from having to output different values, thus breaking the idea of abstraction we are trying to achieve; we'll just output a string that will be printed to the job list.
    }
}
class Estimate_sidewall implements Estimator
{
    private $width, $height, $type;
    function __construct ($drywallType, $width, $height)
    {
        $this->width = $width;
        $this->height = $height;
        $this->type = $drywallType;
    }

    function Estimate ()
    {
        return $this->width * $this->height * 1.12; // 1.12 a square foot, again consider a binary math library
    }

    function BuildInfo ()
    {
        return "SideWall type '{$this->type}' {$this->width}ft x {$this->height}ft = ". ($this->width * $this->height) ."sqft.";
    }
}

$gutter = new Estimate_gutter(100, "Type to gutter"); //pass this to the view

$gutter->Estimate(); //this would be run in the view, or be assigned in the controller to a variable for the view.  This must exist, because it is implementing the Estimator class.  The reason for this is so that you don't need to know what class type it is in the view, you just need to call the same function, no matter what.

/*
    This would print out all the information needed to retrieve
    the needed product.  It is important this function always returns
    the *exact* same data type every time for every class, otherwise
    the abstraction will break. (because if you output an array for one,
    and a string for another, how do you know when to deal with an array,
    and when to deal with a string? You'd need to know what type of estimate
    you're making, and you're attempting to eliminate needing to know that
    using this design pattern).
*/
echo $gutter->BuildInfo ();

虽然我很想看到这个问题的其他模式和解决方案,但它并不是独一无二的,但一个好的解决方案可能很难制定。

于 2012-05-23T01:51:59.257 回答