我將從一個非常天真的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