我将从一个非常幼稚的 OO 版本开始工作,到被认为是“好的”OO 代码,使用多态行为并避免全局状态。
1. 非多态,具有全局静态数据
这很糟糕,因为它实际上只是过程代码的包装对象。它需要一个函数映射来调用每种类型的平台。
class Platform {
private static $platformArray = array(
'ps3' => array(
'displayName'=>'playstation 3',
'function'=>'funcPS3'
),
'xbox' => array(
'displayName'=>'Xbox',
'function'=>'funcXbox'
)
);
private $type;
public function __construct($type) {
if (!array_key_exists($type, self::$platformArray)) {
throw new Exception("Invalid Platform type $type" );
}
$this->type = $type;
}
public function printCode() {
// This was a question embedded within your question, you can use
// http://php.net/manual/en/function.call-user-func.php
// and pass an instance with a method name.
return call_user_func( array($this, self::$platformArray[$this->type]) );
}
private function funcPS3(){
echo 'ps3 specific code';
}
private function funcXbox(){
echo 'xbox specific code';
}
}
$plat = new Platform($_POST['platform']);
$plat->printCode();
2. 多态...但它仍然使用全局数据
通过创建基类,您可以在子类中实现行为,为每个关注点创建单独的类。这里最大的问题是子类需要在全局注册表中注册。
abstract class Platform {
abstract protected function getCode();
public function printCode() {
echo $this->getCode();
}
private function __construct() {} // so only factory can instantiate it
private static $platformArray = array();
public static function create($type) {
if (!array_key_exists($type, self::$platformArray)) {
throw new Exception("Invalid Platform type $type" );
}
return new self::$platformArray[$type];
}
public static function addPlatform($type, $ctor) {
if (!is_subclass_of($ctor, 'Platform')) {
throw new Exception("Invalid Constructor for Platform $ctor" );
}
self::$platformArray[$type] = $ctor;
}
}
class PlatformXBox extends Platform{
protected function getCode() {
return 'xbox specific code';
}
}
Platform::addPlatform('xbox', 'PlatformXBox');
class PlatformPs3 extends Platform {
protected function getCode() {
return 'ps3 specific code';
}
}
Platform::addPlatform('ps3', 'PlatformPs3');
$plat = Platform::create($_POST['platform']);
$plat->printCode();
3.多态,无全局数据
通过将代码放入命名空间,您可以避免基类中的静态代码,并避免将后参数直接映射到类中的危险。
namespace platform {
interface IPlatform {
public function getDisplayName();
public function getCode();
}
class PlatformFactory {
static public function create($platformType) {
$className = "\\platform\\$platformType";
if ( !is_subclass_of($className, "\\platform\\IPlatform") ){
return null;
}
return new $className;
}
}
class Xbox implements IPlatform {
public function getDisplayName(){
return 'xbox';
}
public function getCode(){
return 'xbox code';
}
}
class Ps3 implements IPlatform {
public function getDisplayName(){
return 'ps3';
}
public function getCode(){
return 'ps3 code';
}
}
}
现在您可以像下面这样使用这些类
$platform = platform\PlatformFactory::create('xbox');
echo $platform->getCode() ."\n" ;
$platform2 = platform\PlatformFactory::create('ps3');
echo $platform2->getDisplayName()."\n";
$noPlatform = platform\PlatformFactory::create('dontexist');
if ($noPlatform) {
echo "This is bad, plaftorm 'dontexist' shouldn't have been created";
} else {
echo "Platform 'dontexist' doesn't exist";
}