12

假设我有以下结构:

abstract class Hand {}

class Rock extends Hand {}
class Paper extends Hand {}
class Scissors extends Hand {}

目标是创建一个函数(或方法)Hand::compareHands(Hand $hand1, Hand $hand2),它将在剪刀石头布比赛中返回获胜的手。

用一堆ifs 会很容易,但关键是要有一个更健壮的结构,它依赖于多态性而不是过程代码。

PS 这是在实际生产代码中完成的,如果有人问的话。这不是某种挑战或家庭作业。(这不是真正的石头剪刀布,但你明白了)。

4

3 回答 3

12

你的手的唯一性质是它正在击败另一只手。

然后你不想重复代码,同时每个手形都有一个具体的类型,所以你需要参数化。根据您可以允许的自由级别,这可以像受保护的成员一样简单:

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 的答案进行比较,谁应该获得实际代码的学分,我只是对其进行了重新排序。但只有很少。

此外,我需要感谢 @Leigh 以获得更好的功能和参数命名。这应该减少评论的需要。

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 旁边)。

于 2012-10-04T11:50:29.960 回答
5

这个怎么样?

class Scissors extends Hand implements Beats<Paper> {}

其中 Beats<> 是一个通用接口,其签名如下所示:

interface Beats<Hand> {}
于 2012-10-03T21:31:08.520 回答
3

来自 PHP 聊天

OOP 风格

<?php
interface Hand {
    function beats(Hand $hand);
}

class Rock implements Hand {
    public function beats(Hand $hand) {
        return $hand instanceof Scissors;
    }
}
class Paper implements Hand {
    public function beats(Hand $hand) {
        return $hand instanceof Rock;
    }
}

class Scissors implements Hand {
    public function beats(Hand $hand) {
        return $hand instanceof Paper;
    }
}

简单的功能

<?php
const PAPER = 1;
const ROCK = 2;
const SCISSORS = 3;

function whichHandWon($hand1, $hand2) {
    $winners = [PAPER => ROCK, ROCK => SCISSORS, SCISSORS => PAPER];
    return intval($winners[$hand1] !== $hand2) + 1;
}
于 2012-10-03T21:32:32.387 回答