我們討論了關於IoC控制反轉的設計原則,現在我們用PHP來實現IoC設計原則,加深對這個概念的理解。
首先編寫 Fruit 的 POJO 和 Fruit 接口。繼承 Fruit 接口生成兩個類 Apple 和 Banana,這兩個類都實現了接口的 showColor() 方法。
<?php
/**
* @author Gonn, http://www.bkjia.com/
*/
interface Fruit {
public function showColor();
}
class Apple implements Fruit {
private $color;
function getColor(){
return $this->color;
}
function setColor($value){
$this->color=$value;
}
function showColor(){
echo "Apple Color:" . $this->color;
}
}
class Banana implements Fruit {
private $color;
function getColor(){
return $this->color;
}
function setColor($value){
$this->color=$value;
}
function showColor(){
echo "Banana Color:" . $this->color;
}
}
?>
類工廠實現了一些簡單功能,能夠解析指定的配置文件,並根據配置文件生成類,同時設置指定的屬性值:
<?php
/**
* @author Gonn, http://www.bkjia.com/
*/
class ClassFactory {
private $arr_conf;
function ClassFactory($config_file){
//讀取配置文件內容
$handle = fopen($config_file, r);
$content = fread($handle, filesize($config_file));
fclose($handle);
//去除注釋
$content=preg_replace("<\/\/.*?\s>","",$content);
//轉成數組
$this->arr_conf=json_decode($content,true);
}
function getBean($class_id){
//查找匹配 $class_id 的類
while(true){
//挨個測試
$conf=each($this->arr_conf);
//找不到,返回 null
if($conf==false) return null;
if(strcmp($class_id,$conf["value"]["id"])===0){
//如果匹配則裝入類文件
include_once($conf["value"]["class_file"]);
//生成類的實例
//print_r($conf["value"]["class_name"]);
$obj=new $conf["value"]["class_name"]();
//查找被設置的屬性
$arr_prop=$conf["value"]["properties"];
while($prop=each($arr_prop)){
//生成屬性的設置方法 setXXX ,第一個字母大寫
$set_method="set". ucwords($prop["value"]["name"]);
//調用設置方法,並設置預設值
$obj->$set_method($prop["value"]["value"]);
}
//找到第一個,返回實例
return $obj;
}
}
}
}
?>
//備注使用雙反斜桿
[
{
//類ID,方便工廠查找
"id": "Apple",
//類名
"class_name":"Apple",
//類文件
"class_file":"Fruit.php",
//屬性設置
"properties":[
{
"name":"color",
"value":"Red"
}
]
},
{
"id": "Banana",
"class_name":"Banana",
"class_file":"Fruit.php",
"properties":[
{
"name":"color",
"value":"Yellow"
}
]
}
]
為類工廠指定上述配置文件。我們可以看見,對配置文件裡的不同ID,返回了不同的類實例。調用每個實例的方法,分別輸出了Red和Yellow。可見,我們只需要改變配置文件的內容,就可以返回不同的類實例,而不需修改程序源代碼。這就實現了簡單的 IOC 或者 DI。
<?php
include_once("ClassFactory.php");
$factory = new ClassFactory("config.json");
$fruit = $factory->getBean("Apple");
echo $fruit->showColor() .'<br />';
$fruit = $factory->getBean("Banana");
echo $fruit->showColor() .'<br />';
?>
PHP是動態語言,利用一些語言特性,實現起來很簡單,也沒用到反射之類的概念。
程序運行結果
Apple Color:Red Banana Color:Yellow