PHP设计模式
我有一个反复出现的问题,我目前正在这样处理- 一个POST变量进入到有平台的脚本中,该平台来自一个列表,例如:xbox、ps3、pc、mobileapp、mobilegame等 对于每个不同的平台,我希望能够在我的脚本中执行不同的操作,但在某些情况下,我希望代码能够执行非常类似的操作,此时我执行以下操作:PHP设计模式,php,oop,design-patterns,Php,Oop,Design Patterns,我有一个反复出现的问题,我目前正在这样处理- 一个POST变量进入到有平台的脚本中,该平台来自一个列表,例如:xbox、ps3、pc、mobileapp、mobilegame等 对于每个不同的平台,我希望能够在我的脚本中执行不同的操作,但在某些情况下,我希望代码能够执行非常类似的操作,此时我执行以下操作: $platformArray = array( 'ps3'=>array('displayName'=>'playstation 3','function'=>'fun
$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';
}
我想在我的代码中采用面向对象的方法,我想使用对象作为我的数据存储介质,而不是像我现在这样使用数组,但有时我确实需要提前在代码中定义属性,除了对象之外,我如何才能做到以上几点呢?我将从一个非常幼稚的面向对象版本,发展到被认为是“好”的面向对象代码,使用多态行为并避免全局状态 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";
}
我将从一个非常幼稚的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";
}
您可能希望创建一个名为platforms的类,并在该类中为每个平台创建一个不同的方法:
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.
}
}
希望这有帮助。您可能希望创建一个名为platforms的类,并在该类中为每个平台创建一个不同的方法:
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.
}
}
希望这有帮助。我建议您从理解多态性开始。这应该是个好的开始 当您试图基于某个标志创建行为时,应使用相同的接口实现两个类:
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 . '+++';
}
}
这两个类具有相同名称的方法,可以执行不同的操作
$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();
基本上,在这种情况下,您真的不关心您使用的是哪种类型的平台。您需要知道的是,它们都有相同的公共接口。这就是所谓的“多态性行为”。我建议您从理解多态性开始。这应该是个好的开始 当您试图基于某个标志创建行为时,应使用相同的接口实现两个类:
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 . '+++';
}
}
这两个类具有相同名称的方法,可以执行不同的操作
$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();
基本上,在这种情况下,您真的不关心您使用的是哪种类型的平台。您需要知道的是,它们都有相同的公共接口。这被称为“多态行为”。您研究过对象是如何工作的吗?是的,在一个基本的层面上,我知道他们通常有私有的内部变量,你可以通过函数设置和获取,我想提前设置一些我想我可以用变量加载多个对象实例,我想我可以使用${$\u POST['platform']}引用对象。我可以做${$\u POST['platform']}这样的事情吗->myclassfunc()?抱歉,我没有在这里进行设置。我要创建一个具有预定义类似部分的基本“平台”类,然后创建XBOX/PS3/PC类来继承它,并用平台特定的操作重载一些函数。@GigaWatt,您需要一个了解所有类型子类的工厂来知道实例化哪一个,我不认为子类是这里的答案,请看我的答案。。。接下来,你需要在课堂上做更多的阅读。您需要设计自己的类,声明一个新对象,然后调用该对象上的函数来执行任何操作。您研究过对象是如何工作的吗?是的,在一个基本的层面上,我知道他们通常有私有的内部变量,你可以通过函数设置和获取,我想提前设置一些我想我可以用变量加载多个对象实例,我想我可以使用${$\u POST['platform']}引用对象。我可以做${$\u POST['platform']}这样的事情吗->myclassfunc()?抱歉,我没有在这里进行设置。我要创建一个具有预定义类似部分的基本“平台”类,然后创建XBOX/PS3/PC类来继承它,并用平台特定的操作重载一些函数。@GigaWatt,您需要一个了解所有类型子类的工厂来知道实例化哪一个,我不认为子类是这里的答案,请看我的答案。。。接下来,你需要在课堂上做更多的阅读。你需要设计你自己的类,声明一个新的对象,然后在这个对象上调用你的函数来做任何事情。这并不能真正解决这个问题。你将如何调用基于POST变量的方法?我有一个使用OOP和PDO的全功能教程,如果你想看一看的话:[link]正确答案1是更好的选择。这并不能真正解决问题。您将如何基于POST变量调用该方法?如果您想了解:[link]True answer 1是更好的选项,我有一个使用OOP和PDO的全功能教程