Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 要使用的设计模式_Oop_Inheritance_Class Hierarchy - Fatal编程技术网

Oop 要使用的设计模式

Oop 要使用的设计模式,oop,inheritance,class-hierarchy,Oop,Inheritance,Class Hierarchy,我想用以下课程制作程序: 类Player,它存储有关具有get/set函数的播放器的一些信息。 玩家可以是攻击玩家,该玩家将拥有自己的数据和获取/设置功能。 此外,玩家还可以作为保护层,也可以使用与攻击玩家不同的获取/设置功能来获取其他数据 玩家也可以是团队玩家或自由玩家,每个类都有自己的数据等 问题是如何正确地实现层次结构 起初,我想到了多重继承,这无论如何都不好。 比如: 玩家 攻击玩家扩展玩家 保护层扩展播放器 TeamPlayer扩展AttackPlayer或ProtectorPlaye

我想用以下课程制作程序: 类Player,它存储有关具有get/set函数的播放器的一些信息。 玩家可以是攻击玩家,该玩家将拥有自己的数据和获取/设置功能。 此外,玩家还可以作为保护层,也可以使用与攻击玩家不同的获取/设置功能来获取其他数据

玩家也可以是团队玩家自由玩家,每个类都有自己的数据等

问题是如何正确地实现层次结构

起初,我想到了多重继承,这无论如何都不好。 比如: 玩家 攻击玩家扩展玩家 保护层扩展播放器

TeamPlayer扩展AttackPlayer或ProtectorPlayer FreePlayer扩展攻击玩家或保护层

我还考虑了一些策略模式,但它不适用于这里,因为这里没有通用的算法

有没有什么方法可以帮助组织这种互动

另一种方法是在Player类中有一个字段,这有助于识别TeamPlayer/FreePlayer是攻击型还是保护型,并根据这一点访问适当的字段。 在这种情况下,继承将如下所示:

玩家 TeamPlayer扩展了Player FreePlayer扩展了Player

攻击、保护结构或类而不继承,但作为玩家类中的字段


但是我不喜欢这样的方法,我正在寻找更好的设计。

对于这一点,IMHO继承是错误的模型。相反,我会有一个玩家类和不同的角色。这取决于一个玩家是否可以同时扮演多个角色。我会使用策略模式。

这可能是一个非常方便的问题。这种方法一开始似乎很慢,但在设计不明显时非常有用。TDD倾向于使设计从代码本身浮现出来

如果你有兴趣尝试一下TDD,你可以从我们公司教练写的开始。此外,如果可以的话,请看一下与TDD相关的两集(第6a集和第6b集):它们来自,因此建议您进行讲座/观看

玩家可以是团队玩家或自由玩家

TeamPlayer扩展攻击玩家或保护玩家FreePlayer扩展攻击玩家或保护玩家

我认为,这种方法是可以的。想想如何存储数据。如果您想将其存储在数据库中,这将是一种很好的方法:您拥有包含所有播放器数据的播放器表,并创建其他表(扩展播放器表)来存储不同类型播放器的数据。 看这张照片

事实上,继承层次结构可以大于1,但不能大于4。如果继承是显而易见的,那就没问题了。主要规则是保持低复杂性


另一方面,如果您不打算将此数据存储在db中,或将外键存储在player对象到Free对象等中,则在您的情况下似乎更为明显-使用另一种方法。

它可以是工厂和策略的混合,如下所示:

玩家可以是团队玩家或自由玩家,并且可以使用攻击者或保护者策略。因此,自由球员或团队球员可以继承球员类别,并在其中我们可以关联可以是攻击者或保护者的比赛策略。所以在这种情况下,程序发起人可以调用工厂来决定玩家是自由玩家还是团队玩家,并可以将策略传递给玩家。在播放器中将策略作为关联将有助于保持代码更具可扩展性以添加新策略。玩家类型的工厂和策略是分开的,所以可以独立扩展。使用过多的继承可能会导致代码的性能和维护问题

请不要将“extend”等词视为特定于java的。

和如何


编辑:更新为在接口中添加一个_toString(),这是一个简单的方法组合示例。

我建议使用类似“playerBase”的东西,然后为每个特定的玩家类从中派生。然后你就有了一个数据属性strongtyped。你能为你提到的每种类型的玩家添加一些含义吗?这样就可以清楚地了解在你的场景中,这些玩家之间的联系和区别。
<?php

interface IPlayer {
    public function __toString();
}

class Player implements IPlayer {
    protected $_id;
    protected $_name;

    public function __construct( $id, $name ) { 
        $this->_id = $id;
        $this->_name = $name;
    }
    public function getId() { return $this->_id; }
    public function setId($id) { $this->_id = $id; }
    public function setName($n) { $this->_name = $n; }
    public function getName() { return $this->_name; }

    public function __toString() {
        return 'my name is ' . $this->_name . ' and my id is ' . $this->_id;
    }
}

class ComposedPlayer implements IPlayer {
    protected $_player;

    public function __construct( IPlayer $p ) {
        $this->_player = $p;
    }
    public function __set($k, $v) {
        $this->_player->$k = $v;
    }
    public function __get($k) {
        return $this->_player->$k;
    }
    public function __call($func, $args) {
        return call_user_func_array( array( $this->_player, $func ), $args );
    }
    public function __toString() {
        return $this->_player->__toString();
    }
}

class AttackPlayer extends ComposedPlayer {
    function getNameMod() {
        return 'attack player ' . $this->getName();
    }
    public function __toString() {
        return parent::__toString() . ' and im an attack player';
    }
}

class ProtectedPlayer extends ComposedPlayer {
    function getNameMod() {
        return 'protected player ' . $this->getName();
    }
    public function __toString() {
        return parent::__toString() . ' and im an protected player';
    }
}

class TeamPlayer extends ComposedPlayer {
    function getIdMod() {
        return $this->getId() - 10;
    }
    public function __toString() {
        return parent::__toString() . ' and im an team player';
    }
}

class FreePlayer extends ComposedPlayer {
    function getIdMod() {
        return $this->getId() + 10;
    }
    public function __toString() {
        return parent::__toString() . ' and im an free player';
    }
}

$free_attack_player = new FreePlayer( new AttackPlayer( new Player( 100, 'John' ) ) );
$free_protected_player = new FreePlayer( new ProtectedPlayer( new Player( 101, 'Bob' ) ) );
$team_attack_player = new TeamPlayer( new AttackPlayer( new Player( 102, 'Bill' ) ) );
$team_protected_player = new TeamPlayer( new ProtectedPlayer( new Player( 104, 'Jim' ) ) );

foreach ( array( $free_attack_player, $free_protected_player, $team_attack_player, $team_protected_player ) as $p ) {
    echo 'id: ', $p->getId(), ' name: ', $p->getName(), ' mod id: ', $p->getIdMod(), ' mod name: ', $p->getNameMod(), PHP_EOL;
}

foreach ( array( $free_attack_player, $free_protected_player, $team_attack_player, $team_protected_player ) as $p ) {
    echo $p, PHP_EOL;
}
id: 100 name: John mod id: 110 mod name: attack player John
id: 101 name: Bob mod id: 111 mod name: protected player Bob
id: 102 name: Bill mod id: 92 mod name: attack player Bill
id: 104 name: Jim mod id: 94 mod name: protected player Jim
my name is John and my id is 100 and im an attack player and im an free player
my name is Bob and my id is 101 and im an protected player and im an free player
my name is Bill and my id is 102 and im an attack player and im an team player
my name is Jim and my id is 104 and im an protected player and im an team player