1

私は現在そのように取り組んでいる再発する問題を抱えています-

プラットフォームを持つスクリプトに入るPOST変数。プラットフォームは、xbox、ps3、pc、mobileapp、mobilegameなどのリストからのものです。

異なるプラットフォームごとに、スクリプトで異なることを実行できるようにしたいのですが、場合によっては、次のようなことを実行するときに、コードで非常によく似た処理を実行したいことがあります。

$platformArray = array(
   'ps3'=>array('displayName'=>'playstation 3','function'=>'funcPS3'),
   'xbox'=>array('displayName'=>'Xbox','function'=>'funcXbox')
)
//similar amongst all platforms code on line below
echo 'you have a :'.$platformArray[$_POST['platform']]['displayName'].' for playing       games';

call_user_func($platformArray[$_POST['platform']['function']);

function funcPS3(){
   echo 'ps3 specific code'; 
}

 function funcXbox(){
   echo 'xbox specific code';
 }

コードでOOPアプローチに移行したいのですが、現在行っているように配列ではなくオブジェクトをデータストレージメディアとして使用したいのですが、事前にコードで属性を定義する必要がある場合があります。どうすればよいでしょうか。上記を行いますが、オブジェクトを使用しますか?

4

3 に答える 3

4

ポリモーフィズムを理解することから始めることをお勧めします。この講義は良いスタートになるはずです。

何らかのフラグに基づいて動作を作成しようとしている場合、同じインターフェイスを持つ 2 つのクラスを実装する必要があります。

class Xbox
{
    private $displayName = 'XBox 360';

    public function identify()
    {
        // Xbox-specific stuff
        return  ':::::::::::'. $this->displayName;
    }
}

class PS3
{

    private $displayName = 'Playstation 3';

    public function identify()
    {
        // playstation-specific stuff
        return '+++'. $this->displayName . '+++';
    }
}

2 つのクラスには、異なることを行う同じ名前のメソッドがあります。

$platform = $_POST['platform'];
// classes in PHP are case-insensitive
// expected values would be:  xbox, Xbox, ps3, pS3
if ( !class_exists($platform) )
{
     echo "Platform '{$platform}' is not supported";
     exit; 
     // since continuing at this point would cause a fatal error, 
     // better to simply exit
}

$object = new $platform;
echo $object->identify();

基本的に、この場合、どのタイプのプラットフォームで作業しているかは気にしません。知っておく必要があるのは、両方が同じパブリック インターフェイスを持っているということだけです。これを「ポリモーフィック動作」と呼びます。

于 2013-02-28T10:56:49.850 に答える
0

非常に素朴な 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. ポリモーフィック、グローバル データなし

コードを名前空間に配置することで、基本クラスの静的コードを回避し、post パラメーターをクラスに直接マッピングする危険を回避できます。

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";
}
于 2013-02-27T21:35:03.057 に答える
0

プラットフォームと呼ばれるクラスを作成し、クラス内にプラットフォームごとに異なるメソッドを作成することができます。

class platforms {
   //Create your variables here, also called properties.
   public $displayName;

   //Create a function, also called a method for each platform you intent to use.
   public function xboxPlatform(){
        //Code comes here what you want to do.
   }
}

お役に立てれば。

于 2013-02-27T21:40:04.427 に答える