假设我具有以下结构:
abstract class Hand {}
class Rock extends Hand {}
class Paper extends Hand {}
class Scissors extends Hand {}
目标是制作一个函数(或方法)
Hand::compareHands(Hand $hand1, Hand $hand2)
,该函数将在剪刀石头布的比赛中返回获胜的手。使用一堆
if
会很容易,但是重点是要有一个更健壮的结构,它依赖于多态性而不是过程代码。P.S.如果有人问,这是在实际的生产代码中完成的。这不是某种挑战或作业。 (这不是真正的剪刀布,但您明白了)。
最佳答案
您的手的唯一性质是它在击败另一只手。
然后,您不希望在重复使用每种手形的一种具体类型时重复代码,因此需要进行参数化。根据您允许的自由级别,这可以像 protected 成员一样简单:
abstract class Hand {
protected $beats;
final public function beats(Hand $opponent) {
return $opponent instanceof $this->beats;
}
}
class Rock extends Hand {
protected beats = 'Scissors';
}
class Paper extends Hand {
protected beats = 'Rock';
}
class Scissors extends Hand {
protected beats = 'Paper';
}
我认为这是这里的标准模板方法模式,形式非常简单。将此与Lusitanian's answer进行比较,后者应该获得实际代码的积分,我只是对它进行了一些重新排序。但是只有一点点。
另外,我需要对@Leigh for the far better function and parameter naming表示感谢。这应该减少评论的需要。
Lusistanian建议的第二种选择可以用策略模式来表示。这也有些直截了当:
class EvaluateHands
{
private $rules;
public function __construct(array $rules)
{
$this->rules = $rules;
}
public function compareHands(Hand $hand1, Hand $hand2)
{
return $this->rules[get_class($hand1)] === get_class($hand2) ? $hand1 : $hand2;
}
}
new EvaluateHands(
array(
'Rock' => 'Scissors',
'Paper' => 'Rock',
'Scissor' => 'Paper'
)
);
两只手之间的比较已完全封装到EvaluateHands
类型中,该类型甚至可以配置(如果游戏规则发生变化),而两只手则保持不变:abstract class Hand {}
class Rock extends Hand {}
class Paper extends Hand {}
class Scissors extends Hand {}
此代码的版权归gordon(在Lusistanian旁边)。关于php - 如何描述三个项目之间的剪刀石头布关系?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12717149/