Php 从对象中删除过多的IF
编辑: 我应该提到我希望它更面向对象。我不认为我的代码接近OO,也不使用开关,是吗 作品: 首先,在我下面的例子中,我使用的是荷兰单位,所以计算可能看起来不正确,但你会明白的 基本上,我有一份商品清单。例如,在我的数据库中,我将价格按件或按磅存储。因此,为了计算每种产品的总价格,根据选择的数量,我正在与下面的班级合作 例如: 在我的杂货店列表中,我有一些产品,产品后面是一个文本字段和一个下拉列表。在文本字段中,我可以输入我想要的数量,并在下拉列表中选择是否需要盎司、磅等。基于这些值,以及数据库中的初始价格(每件的价格等),我可以计算每个产品的总价格 我的问题是:Php 从对象中删除过多的IF,php,oop,object,Php,Oop,Object,编辑: 我应该提到我希望它更面向对象。我不认为我的代码接近OO,也不使用开关,是吗 作品: 首先,在我下面的例子中,我使用的是荷兰单位,所以计算可能看起来不正确,但你会明白的 基本上,我有一份商品清单。例如,在我的数据库中,我将价格按件或按磅存储。因此,为了计算每种产品的总价格,根据选择的数量,我正在与下面的班级合作 例如: 在我的杂货店列表中,我有一些产品,产品后面是一个文本字段和一个下拉列表。在文本字段中,我可以输入我想要的数量,并在下拉列表中选择是否需要盎司、磅等。基于这些值,以及数据库中
public function calculate()
{
if($this->unit === 'ounce')
{
return $this->formatOunce();
}
if($this->unit === 'pound')
{
return $this->formatPound();
}
return $this->formatOne();
}
我将如何更改上述代码以使其成为良好的OO?我是使用存储库还是使用接口?或者我可以在这个特定的类中这样做以保持简单?我觉得“如果”太多了。我建议立即进行两项更改: 使用类常量而不是硬编码的字符串标识符。优点有两个:IDE提供更好的自动完成支持,并且没有更多的打字错误 使用switch语句,可以让事情更清楚: 这也将允许有一个计算目录和一个方法,而不是几个独立的方法来进行实际的计算,因为您可以将公式存储在数组甚至静态类中 最后还有一件更基本的事情:我想在这里讨论架构方法:
为什么选择实现类计算?这让我觉得很不直观。。。实现类似PositionInShoppingCart的东西不是更自然吗?这样,此类对象就可以保存产品标识符、基本价格、数量/金额等?这将以自然的方式导致ShoppingCart类。。。该类型的对象将包含第一种类型的对象列表 我建议立即进行两项更改: 使用类常量而不是硬编码的字符串标识符。优点有两个:IDE提供更好的自动完成支持,并且没有更多的打字错误 使用switch语句,可以让事情更清楚: 这也将允许有一个计算目录和一个方法,而不是几个独立的方法来进行实际的计算,因为您可以将公式存储在数组甚至静态类中 最后还有一件更基本的事情:我想在这里讨论架构方法:
为什么选择实现类计算?这让我觉得很不直观。。。实现类似PositionInShoppingCart的东西不是更自然吗?这样,此类对象就可以保存产品标识符、基本价格、数量/金额等?这将以自然的方式导致ShoppingCart类。。。该类型的对象将包含第一种类型的对象列表 您不想切换到交换机吗 首先,从概念上和逻辑上来说,转换是正确的选择。您正在使用一个变量$this->unit切换值。我觉得它看起来真的很干净。[] 第二,它更快。虽然在你的情况下,可能没那么重要
$res = NULL;
switch($this->unit)
{
case 'ounce': $res = $this->formatOunce(); break;
case 'pound': $res = $this->formatPound(); break;
default: $res = $this->formatOne();
}
return $res;
你不想换到另一台吗 首先,从概念上和逻辑上来说,转换是正确的选择。您正在使用一个变量$this->unit切换值。我觉得它看起来真的很干净。[] 第二,它更快。虽然在你的情况下,可能没那么重要
$res = NULL;
switch($this->unit)
{
case 'ounce': $res = $this->formatOunce(); break;
case 'pound': $res = $this->formatPound(); break;
default: $res = $this->formatOne();
}
return $res;
编辑问题后要求采用面向对象的方法: 创建一个基类来处理输出总数。它调用执行计算的受保护方法。计算: 现在,您可以使用物品的磅版本扩展基本物品。英镑版本将覆盖计算方法,因为计算方式不同
class PoundItem extends Item
{
protected function calculate($format = true)
{
return $this->price / 1000 * 500 * $this->amount / 100;
}
}
要生成对象,您需要构造函数方法或所谓的工厂来生成它们。这是一个工厂级。它也可以在您的basket类上实现
class ItemFactory
{
static public function create($price, $amount, $type)
{
// this could be implemented in numerous ways
// it could even just be method on your basket
$class = $type . "Item";
return new $class($price, $amount);
}
}
创建英镑类型的新项目:
因为PoundItem也是一个项目,所以可以使用total方法。但是由于我们改变了calculate的实现,它现在可以计算磅
echo $a->total();
编辑问题后要求采用面向对象的方法: 创建一个基类来处理输出总数。它调用执行计算的受保护方法。计算: 现在,您可以使用英镑版本的 这个项目。英镑版本将覆盖计算方法,因为计算方式不同
class PoundItem extends Item
{
protected function calculate($format = true)
{
return $this->price / 1000 * 500 * $this->amount / 100;
}
}
要生成对象,您需要构造函数方法或所谓的工厂来生成它们。这是一个工厂级。它也可以在您的basket类上实现
class ItemFactory
{
static public function create($price, $amount, $type)
{
// this could be implemented in numerous ways
// it could even just be method on your basket
$class = $type . "Item";
return new $class($price, $amount);
}
}
创建英镑类型的新项目:
因为PoundItem也是一个项目,所以可以使用total方法。但是由于我们改变了calculate的实现,它现在可以计算磅
echo $a->total();
你的问题是,你把代码从每个条件中分离出来,放到它们自己的类中:盎司类知道如何计算盎司,磅类知道如何计算磅 正如有人之前所说,你仍然需要某种决定是使用英镑还是盎司的货币。那家工厂看起来。。。嗯,和你现在的情况一模一样,但很可能是从别的地方抽象出来的 由于目前代码非常简单,我认为任何这些更改都会过早地进行重构。你现在所拥有的并不复杂——理解代码的作用不会让这里的人慢下来。一旦你开始用更复杂的方法来计算某件事,那么研究多态性就更合适了
类似地,我认为switch语句与IF条件建议也不是很有用的建议。在这种情况下,它们不会增加任何可读性。您的问题是,将代码从每个条件中分离出来,并将它们放在自己的类中:Ounce类知道如何计算ounces,Pound类知道如何计算pounds 正如有人之前所说,你仍然需要某种决定是使用英镑还是盎司的货币。那家工厂看起来。。。嗯,和你现在的情况一模一样,但很可能是从别的地方抽象出来的 由于目前代码非常简单,我认为任何这些更改都会过早地进行重构。你现在所拥有的并不复杂——理解代码的作用不会让这里的人慢下来。一旦你开始用更复杂的方法来计算某件事,那么研究多态性就更合适了
类似地,我认为switch语句与IF条件建议也不是很有用的建议。在这种情况下,它们不会增加可读性。切换可能是执行ifs的更干净的方法。此外,您可以只使用大括号:返回$this->{$key}请记住,OO不是好代码的黄金标准。如果你问的是更多的OO,你应该删除问题中关于删除ifs的部分。ps:我将删除我的答案,尽管它涉及分离的关注点,但它不是特别的OO。我用一种简单的OO方法更新了我的答案。这应该给你一个好主意。其他答案中似乎没有一个涵盖OO。切换可能是执行ifs的一种更干净的方法。此外,您可以只使用大括号:返回$this->{$key}请记住OO不是好代码的黄金标准。如果你问的是更多的OO,你应该删除问题中关于删除ifs的部分。ps:我将删除我的答案,尽管它涉及分离的关注点,但它不是特别的OO。我用一种简单的OO方法更新了我的答案。这应该给你一个好主意。其他答案中似乎没有一个涉及OO。引入额外变量$res只会让事情变得更复杂。。。。为什么?@arkascha我觉得并不复杂。将值赋给$res并到达代码末尾更像是一种标准做法。他们说,如果在代码中间发出return语句,这是一个坏习惯,也是一个麻烦制造者,但是如果它对您有效,并且没有真正引起维护问题,那么应该这样做。这里有一个秘密,我喜欢使用GO TO,即使人们认为这是一个麻烦我没有遇到麻烦。这真的取决于你如何使用它或什么对你方便。我同意这是个人品味和习惯的问题。对我来说,这要复杂得多,因为很明显,很难跟上潮流。还有更高的风险,例如,您可能会在稍后意外修改$res,可能是因为缺少休息或类似的原因…是的,我编辑了我的问题,因为它确实是作为个人品味和习惯问题制定的,现在通过编辑,应该可以更清楚地了解我想要什么,真的。引入额外的变量$res只会让事情变得更复杂。。。。为什么?@arkascha我觉得并不复杂。将值赋给$res并到达代码末尾更像是一种标准做法。他们说,如果在代码中间发出return语句,这是一个坏习惯,也是一个麻烦制造者,但是如果它对您有效,并且没有真正引起维护问题,那么应该这样做。这里有一个秘密,我喜欢使用GO TO,即使人们认为这是一个麻烦
. : 我没有遇到麻烦。这真的取决于你如何使用它或什么对你方便。我同意这是个人品味和习惯的问题。对我来说,这要复杂得多,因为很明显,很难跟上潮流。还有更高的风险,例如,您可能会在稍后意外修改$res,可能是因为缺少休息或类似的原因…是的,我编辑了我的问题,因为它确实是作为个人品味和习惯问题制定的,现在通过编辑,应该可以更清楚地了解我想要什么,真的。我想这就是我需要知道的全部:我想这就是我需要知道的全部:我留下了我的旧答案,因为还有一些部分,比如常数和关注点的分离,我认为你可以利用。是的,这些东西非常有意义,我可以用它,谢谢:我留下了我以前的答案,因为还有一些部分,比如const和关注点的分离,我认为你可以利用。是的,这些东西非常有意义,我可以处理这些,谢谢: