設計準則中的開閉原則,即無需修改任何一行程序代碼,將功能加入至原先的應用程序中,也可以在不修改任何程序的情況下移除。
某地區有各種不同的商店,每家商店都賣四種水果:蘋果十元一個、香蕉二十元一個、橘子三十元一個、西瓜四十元一個,顧客可以在任意商店進行購買,每家商店需要可以隨時向稅務局提供總銷售額。
class Shop
{
// 商店的名字
private $name;
// 商店的總銷售額
private $turnover = 0;
public function __construct($name){
$this->name = $name;
}
// 售賣商品
public function sell($commodity){
switch ($commodity){
case 'apple':
$this->turnover += 10;
echo "賣出一個蘋果<br/>";
break;
case 'banana':
$this->turnover += 20;
echo "賣出一個香蕉<br/>";
break;
case 'orange':
$this->turnover += 30;
echo "賣出一個橘子<br/>";
break;
case 'watermelon':
$this->turnover += 40;
echo "賣出一個西瓜<br/>";
break;
}
}
// 顯示商店目前的總銷售額
public function getTurnover(){
echo $this->name.'目前爲止的銷售額爲:'.$this->turnover;
}
}
// 顧客類
class Human
{
//從商店購買商品
public function buy(Shop $shop,$commodity){
$shop->sell($commodity);
}
}
// new一個名爲kfc的商店
$kfc = new Shop('kfc');
// new一個名爲mike的顧客
$mike = new Human();
// mike從kfc買了一個蘋果
$mike->buy($kfc,'apple');
// mike從kfc買了一個香蕉
$mike->buy($kfc,'banana');
// 輸出kfc的總營業額
echo $kfc->getTurnover();
可以看到,雖然代碼完成了對目前需求的實現,但是此時的 shell() 方法依賴於具體的實踐並且擁有絕對的控制權。一旦我們需要在商店加入一個新的商品,比如芒果mango,那我們不得不去修改商店類的 sell() 方法,違反了 OCP 原則,即對擴展開放,對修改關閉。
abstract class Fruit
{
public $name;
public $price;
}
class Shop
{
//商店的名字
private $name;
//商店的總銷售額
private $turnover = 0;
public function __construct($name){
$this->name = $name;
}
//售賣商品
public function sell(Fruit $commodity){
$this->turnover += $commodity->price;
echo '賣出一個'.$commodity->name.',收入'.$commodity->price."元<br/>";
}
//顯示商店目前的總銷售額
public function getTurnover(){
echo $this->name.'目前爲止的銷售額爲:'.$this->turnover;
}
}
//顧客類
class Human
{
//從商店購買商品
public function buy(Shop $shop,$commodity){
$shop->sell($commodity);
}
}
class Apple extends Fruit
{
public $name = 'apple';
public $price = 10;
}
class Bananae extends Fruit
{
public $name = 'banana';
public $price = 20;
}
class Orange extends Fruit
{
public $name = 'orange';
public $price = 30;
}
class Watermelon extends Fruit
{
public $name = 'watermelon';
public $price = 40;
}
//new一個名爲kfc的商店
$kfc = new Shop('kfc');
//new一個名爲mike的顧客
$mike = new Human();
//mike從kfc買了一個蘋果
$mike->buy($kfc,new Apple());
//mike從kfc買了一個香蕉
$mike->buy($kfc,new Bananae());
//輸出kfc的總營業額
echo $kfc->getTurnover();
採用依賴注入可以快速進行代碼擴展,
class Lemon extends Fruit
{
public $name = 'Lemon';
public $price = 50;
}