Jef*_*ffz 5 php oop polymorphism interface
可以使用不同的工具完成相同的事情.我在下面的例子中也是如此.
一个显示了interface/polymorphism的使用(来源:nettuts - 我认为).另一个直接的类交互(我的) - 它也显示了一些多态性(通过call_tool()).
你能告诉我,你认为哪种方式更好.
哪个更安全,更稳定,防篡改,面向未来(关注代码开发).
请仔细检查两者中使用的范围/可见性.
您的一般建议,这是最好的编码实践.
接口:
class poly_base_Article {
public $title;
public $author;
public $date;
public $category;
public function __construct($title, $author, $date, $category = 0, $type = 'json') {
$this->title = $title;
$this->author = $author;
$this->date = $date;
$this->category = $category;
$this->type = $type;
}
public function call_tool() {
$class = 'poly_writer_' . $this->type . 'Writer';
if (class_exists($class)) {
return new $class;
} else {
throw new Exception("unsupported format: " . $this->type);
}
}
public function write(poly_writer_Writer $writer) {
return $writer->write($this);
}
}
interface poly_writer_Writer {
public function write(poly_base_Article $obj);
}
class poly_writer_xmlWriter implements poly_writer_Writer {
public function write(poly_base_Article $obj) {
$ret = '';
$ret .= '' . $obj->title . '';
$ret .= '' . $obj->author . '';
$ret .= '' . $obj->date . '';
$ret .= '' . $obj->category . '';
$ret .= '';
return $ret;
}
}
class poly_writer_jsonWriter implements poly_writer_Writer {
public function write(poly_base_Article $obj) {
$array = array('article' => $obj);
return json_encode($array);
}
}
$article = new poly_base_Article('Polymorphism', 'Steve', time(), 0, $_GET['format']);
echo $article->write($article->call_tool());
非接口
class npoly_base_Article {
public $title;
public $author;
public $date;
public $category;
public function __construct($title, $author, $date, $category = 0, $type = 'json') {
$this->title = $title;
$this->author = $author;
$this->date = $date;
$this->category = $category;
$this->type = $type; //encoding type - default:json
}
public function call_tool() {
//call tool function if exist
$class = 'npoly_writer_' . $this->type . 'Writer';
if (class_exists($class)) {
$cls = new $class;
return $cls->write($this);
} else {
throw new Exception("unsupported format: " . $this->type);
}
}
}
class npoly_writer_jsonWriter {
public function write(npoly_base_Article $obj) {
$array = array('article' => $obj);
return json_encode($array);
}
}
class npoly_writer_xmlWriter {
public function write(poly_base_Article $obj) {
$ret = '';
$ret .= '' . $obj->title . '';
$ret .= '' . $obj->author . '';
$ret .= '' . $obj->date . '';
$ret .= '' . $obj->category . '';
$ret .= '';
return $ret;
}
}
$article = new npoly_base_Article('nPolymorphism', 'Steve', time(), 0, $_GET['format']);
echo$article->call_tool();
MikeSW代码(如果我做对了)
class poly_base_Article {
private $title;
private $author;
private $date;
private $category;
public function __construct($title, $author, $date, $category = 0) {
$this->title = $title;
$this->author = $author;
$this->date = $date;
$this->category = $category;
}
public function setTitle($title) {
return $this->title = $title;
}
public function getTitle() {
return $this->title;
}
public function getAuthor() {
return $this->author;
}
public function getDate() {
return $this->date;
}
public function getCategory() {
return $this->category;
}
}
interface poly_writer_Writer {
public function write(poly_base_Article $obj);
}
class poly_writer_xmlWriter implements poly_writer_Writer {
public function write(poly_base_Article $obj) {
$ret = '';
$ret .= '' . $obj->getTitle() . '';
$ret .= '' . $obj->getAuthor() . '';
$ret .= '' . $obj->getDate() . '';
$ret .= '' . $obj->getCategory() . '';
$ret .= '';
return $ret;
}
}
class poly_writer_jsonWriter implements poly_writer_Writer {
public function write(poly_base_Article $obj) {
//array replacement
//$obj_array = array('title' => $obj->getTitle(), 'author' => $obj->getAuthor(), 'date' => $obj->getDate(), 'category' => $obj->getCategory());
//$array = array('article' => $obj_array);
$array = array('article' => $obj); //$obj arrives empty
return json_encode($array);
}
}
class WriterFactory {
public static function GetWriter($type='json') {
switch ($type) {
case 'json':
case 'xml': $class = 'poly_writer_' . $type . 'Writer';
return new $class;
break;
default: throw new Exception("unsupported format: " . $type);
}
}
}
$article = new poly_base_Article('nPolymorphism', 'Steve', time(), 0);
$writer=WriterFactory::GetWriter($_GET['format']);
echo $writer->write($article);
咳咳,无论什么版本,你的方法都有一些缺陷。首先,poly_base_Article 公开了破坏封装的字段,并且有点违背了使用 OOP 的目的。
接下来,您可以通过 $_GET 参数进行精细注入。正确的上课方式应该是这样
class poly_base_Article {
private $title;
private $author;
private $date;
private $category;
public function __construct($title, $author, $date, $category = 0) {
$this->title = $title;
$this->author = $author;
$this->date = $date;
$this->category = $category;
}
public function getTitle() { return $this->title;}
//...other getters defined here...
public function AsArray()
{
return (array) $this;
}
//this could be removed
public function write(poly_writer_Writer $writer) {
return $writer->write($this);
}
}
Run Code Online (Sandbox Code Playgroud)
不过 write方法似乎不是必需的,您只需告诉 writer 直接写入对象即可。
*call_tool* 方法应该属于服务或作为工厂方法来创建 poly_writer_Writer 的实例(顺便说一句,您应该将类和接口的命名更改为更自然的名称),如下所示
class WriterFactory
{
public static function GetWriter($type='json')
{
switch($type)
{
case 'json'
case 'xml': $class= 'poly_writer_' . $type . 'Writer';
return new $class;
break;
default: throw new Exception("unsupported format: " . $type);
}
}
}
$article = new poly_base_Article('nPolymorphism', 'Steve', time(), 0);
$writer=WriterFactory::GetWriter(, $_GET['format']);
echo $writer->write($article);
Run Code Online (Sandbox Code Playgroud)
哪个更安全、更稳定、防篡改、面向未来(就afa代码开发而言)。
这仅取决于开发人员的技能和纪律。在这种特殊情况下,我编写的代码更安全、防篡改且面向未来:P
更新 确实,我忘记将 getters 放在 poly_base_Article 中,我现在已经添加了它们。由于您正在进行序列化,因此文章不应该知道它,因为这不是他的责任(它是基础设施层的一部分),因此根本不需要 write 方法,但这是这里的一个特定情况(在一切都取决于关于上下文)。
WriterFactory 基本上是工厂模式,它创建编写器的实例并返回抽象- 这就是接口有用的多态性。这种方法使得添加接口的新实现变得非常容易,并且还可以防止代码注入。开关是检查是否只允许 $type 的有效值。您可以在其他地方验证 $type,但这是唯一应该处理与创建编写器相关的所有内容的地方。即使您想在外部进行验证,您也只需在 WriterFactory 中创建一个静态方法,该方法将返回 true/false 并使用 not。
关于接口成为一种时尚......使用接口是 OOP 应该如何完成的。针对抽象进行编程是最佳实践,而接口是“最佳”抽象。坦率地说:如果接口是一种时尚,那么 OOP 就是一种时尚。
关于你的第二个例子,第一个例子也是如此,创建作者的方法一开始就不应该存在,因为它将作者的创建与文章结合起来,而这两个例子几乎没有任何共同点。这违反了 SRP(单一责任原则)。
在这种特殊情况下,一旦您在单独的类中创建创建工厂,那么您几乎不关心接口,但是因为这里的用法非常简单,并且您使用的是 PHP 或松散类型语言。如果您将编写器作为依赖项传递,那么它将有助于传递接口而不是实际的实现(就像您在第一个示例中所做的那样)。了解您传递的是什么类型非常有帮助。
另外,在像 C# 这样的语言中,您将有一个返回类型,然后,作为最佳用法,您将它作为接口类型返回(C# 支持动态类型,可以说其行为有点像 PHP 中,因此您可以返回动态类型,而不是返回动态类型)。小心,但这会带来性能损失,如果返回的类型没有调用的方法,则会抛出异常)
| 归档时间: |
|
| 查看次数: |
2561 次 |
| 最近记录: |