在MVC构建的应用程序中,哪种设计模式最适合此场景?

时间:2013-08-13 11:40:30

标签: php design-patterns model-view-controller

让我们说我们有一个应用程序,人们可以创建角色,类似于魔兽世界或无尽的任务。我们选择使用MVC。

我们需要在登录应用程序后从其主页向用户显示一个字符列表。最初,向用户显示其字符列表的唯一业务要求是检索与用户帐户关联的所有活动字符的列表。 此字符列表还需要跨多个控制器访问。

在某些时候,商业模式会发生变化,并且会设置付款状态,以便用户只能根据用户的付款状态查看某些字符。例如,Gold级别的付款状态允许您访问所有字符,银色限制为2种类型的字符等等。

    <?php
    class Controller{
        public function index(){
            //array of users active characters(would be done via lookups with datamapper pattern)
            $arrCharacters = array(0=>$objChar1, 1=>$objChar2);

            //set a payment status of silver(would be done via lookups with datamapper pattern)
            $objPayment = new objPayment();
            $objPayment->setStatus('Silver');

            //loop through each character object and check the character access level against what the user paid for
            //if the character access level is not at least equal to the payment level, remove the character object from the
            //array that we want to pass to the output(view)
            foreach($arrCharacters as $key=>$objCharacter){                
                if($objCharacter->getCharAccessLevel()<=$objPaymentLevel()){
                    unset($arrCharacters[$key]);
                }
            }
        }
    }
    ?>

显然这种方法可行,但这意味着我必须将该功能复制到我需要访问用户角色的每个控制器中。有关解决此问题的更有效方法的任何建议。我看不出一个适合我案例的好设计模式。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

这不是MVC问题,但可以通过界面轻松解决。

例如,您可以创建一个PlayerService接口并创建不同的实现。在这种情况下,免费支付实施。

interface PlayerService {
    public function getPlayers();
}

class FreePlayerService implements PlayerService {
    public function getPlayers() { ... }
}

class PayedPlayerService implements PlayerService {
    private $status;

    public function __construct($status) { ... }
    public function getPlayers() { /* return players based on status */ }
}

控制器

class PlayerController {
    PlayerService $service;

    public function setPlayerService(PlayerService $service) {
        $this->service = $service;
    }

    public function index() {
        $players = $service->getPlayers();
    }
}

现在,您可以将控制器服务设置为其中一个实现,但不会知道其中的差异。