我将从一个非常天真的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.多态...但它仍然使用全局数据
By creating a base class可以实现在子类的行为,对于每一个关心创建单独的类。这里最大的问题是子类需要注册一个全局注册表。
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.多态,没有全球性的数据
By putting your code into a namespace,您避免在基类的静态代码,避免映射后的参数的危险直接进入类。
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";
}
你看过物体是如何工作的吗? [你有什么尝试](http://whathaveyoutried.com)? – UnholyRanger 2013-02-27 21:24:20
耶在基本的水平我明白他们通常有私人的内部变量,你可以设置和获取函数,我想提前设置一些,我想我可以加载变量的对象的多个实例,我想我可以参考我可以做$ {$ _ POST ['platform']} - > myclassfunc(); ?道歉没有尝试它我没有得到我的设置在这里 – arcanine 2013-02-27 21:29:10
我会做一个基地“平台”类与预定义类似的部分,然后使XBOX/PS3/PC类继承它,并重载一些功能的平台具体行动。 – 2013-02-27 21:33:31