php面向物件程式設計5大原則+6大設計模式
阿新 • • 發佈:2018-12-24
一、面向物件程式設計的6大設計原則
單一職責原則——類要職責單一,一個類只需要做好一件事情。
里氏替換原則——子類可以擴充套件父類的功能,但不能改變父類原有的功能(可以實現父類的抽象方法和增加自己特有的方法,不要覆蓋父類的非抽象方法)。
依賴倒置原則——-面向介面程式設計:只需關心介面,不需要關心實現。
介面隔離原則——-建立單一介面,儘量細化介面,介面中的方法儘量少。低耦合高內聚。
最少知識原則——-一個類對自己依賴的類知道的越少越好,兩實體間最好不互動或少互動。
開閉原則——-對擴充套件開放,對修改關閉。
二、6大設計模式和應用場景
6大設計模式:單例、工廠、觀察者、介面卡、策略、裝飾器
單例:單例設計模式常應用於資料庫類設計,採用單例模式,只連線一次資料庫,防止開啟多個數據庫連線。
工廠:常用於根據輸入引數的不同或者應用程式配置的不同來建立一種專門用來例項化並返回其對應的類的例項。
觀察者:一模式允許某個類觀察另一個類的狀態,當被觀察的類狀態發生改變的時候,觀察類可以收到通知並且做出相應的動作;觀察者模式為您提供了避免元件之間緊密耦。
介面卡:老程式碼介面不適應新的介面需求,或者程式碼很多很亂不便於繼續修改,或者使用第三方類庫。例如:php連線資料庫的方法:mysql,,mysqli,pdo,可以用介面卡統一
策略:將一組特定的行為和演算法封裝成類,以適應某些特定的上下文環境。例如:一個電商網站系統,針對男性女性使用者要各自跳轉到不同的商品類目,並且所有廣告位展示不同的廣告
裝飾器:動態地新增修改類的功能。
<?php /** * 單例模式 */ class Database { // We need a static private variable to store a Database instance. private static $instance; // Mark as private to prevent it from being instanced. private function __construct() { // Do nothing. } private function __clone() { // Do nothing. } public static function getInstance() { if (!(self::$instance instanceof self)) { self::$instance = new self(); } return self::$instance; } } $a =Database::getInstance(); $b =Database::getInstance(); // true var_dump($a === $b);
<?php
/*
工廠模式
*/
interface InterfaceShape
{
function getArea();
function getCircumference();
}
/**
* 矩形
*/
class Rectangle implements InterfaceShape
{
private $width;
private $height;
public function __construct($width, $height)
{
$this->width = $width;
$this->height = $height;
}
public function getArea()
{
return $this->width* $this->height;
}
public function getCircumference()
{
return 2 * $this->width + 2 * $this->height;
}
}
/**
* 圓形
*/
class Circle implements InterfaceShape
{
private $radius;
function __construct($radius)
{
$this->radius = $radius;
}
public function getArea()
{
return M_PI * pow($this->radius, 2);
}
public function getCircumference()
{
return 2 * M_PI * $this->radius;
}
}
/**
* 形狀工廠類
*/
class FactoryShape
{
public static function create()
{
switch (func_num_args()) {
case 1: return new Circle(func_get_arg(0));break;
case 2: return new Rectangle(func_get_arg(0), func_get_arg(1));break;
default: break;
}
}
}
$rect =FactoryShape::create(5,5);
// object(Rectangle)#1 (2) { ["width":"Rectangle":private]=> int(5) ["height":"Rectangle":private]=> int(5) }
var_dump($rect);
echo "<br>";
// object(Circle)#2 (1) { ["radius":"Circle":private]=> int(4) }
$circle =FactoryShape::create(4);
var_dump($circle);
<?php
/*
觀察者模式
*/
// 可被觀察者介面
interface InterfaceObservable
{
function addObserver($observer);
function removeObserver($observer_name);
}
// 觀察者介面
interface InterfaceObserver
{
function onListen($sender, $args);//$sender被觀察者物件,$args被觀察內容
function getObserverName();
}
// 可被觀察者抽象類
abstract class Observable implements InterfaceObservable
{
protected $observers = array();
public function addObserver($observer)
{
if ($observer instanceof InterfaceObserver)
{
$this->observers[] = $observer;
}
}
public function removeObserver($observer_name)
{
foreach ($this->observers as $index => $observer)
{
if ($observer->getObserverName() === $observer_name)
{
array_splice($this->observers, $index, 1);
return;
}
}
}
}
// 觀察者抽象類
abstract class Observer implements InterfaceObserver
{
protected $observer_name;
function getObserverName()
{
return $this->observer_name;
}
function onListen($sender, $args)
{
}
}
// 模擬一個可以被觀察的類
class A extends Observable
{
public function addListener($listener)
{
foreach ($this->observers as $observer)
{
$observer->onListen($this, $listener);
}
}
}
// 模擬一個觀察者類
class B extends Observer
{
protected $observer_name = 'B';
public function onListen($sender, $args)
{
var_dump($sender);
echo "<br>";
var_dump($args);
echo "<br>";
}
}
// 模擬另外一個觀察者類
class C extends Observer
{
protected $observer_name = 'C';
public function onListen($sender, $args)
{
var_dump($sender);
echo "<br>";
var_dump($args);
echo "<br>";
}
}
$a = new A();
// 注入觀察者
$a->addObserver(new B());
$a->addObserver(new C());
// 可以看到觀察到的資訊
$a->addListener('D');//A物件(B,C物件在其陣列中),D
// 移除觀察者
$a->removeObserver('B');
$a->addListener('D');//object(B,C物件在其陣列中),D
// 列印的資訊:
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
// object(A)#1 (1) { ["observers":protected]=> array(2) { [0]=> object(B)#2 (1) { ["observer_name":protected]=> string(1) "B" } [1]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
// object(A)#1 (1) { ["observers":protected]=> array(1) { [0]=> object(C)#3 (1) { ["observer_name":protected]=> string(1) "C" } } }
// string(1) "D"
<?php
/*
裝飾器模式
*/
interface Decorator{
public function display();
}
class XiaoFang implements Decorator{
private $name;
public function __construct($name){
$this->name = $name;
}
public function display(){
echo "我是".$this->name.",我出門了!!!"."<br>";
}
}
class Finery implements Decorator{
private $component;
public function __construct(Decorator $component){
$this->component=$component;
}
public function display(){
$this->component->display();
}
}
class Shoes extends Finery{
public function display(){
echo "穿上鞋子"."<br>";
parent::display();
}
}
class Skirt extends Finery{
public function display(){
echo "穿上裙子"."<br>";
parent::display();
}
}
class Fire extends Finery{
public function display(){
echo "出門前先整理頭髮"."<br>";
parent::display();
echo "出門後再整理一下頭髮"."<br>";
}
}
$xiaofang=new XiaoFang("小芳");
$shoes=new Shoes($xiaofang);
$skirt=new Skirt($shoes);
$fire=new Fire($skirt);
$fire->display();
// 輸出結果:
// 出門前先整理頭髮
// 穿上裙子
// 穿上鞋子
// 我是小芳,我出門了!!!
// 出門後再整理一下頭髮
<?php
/*
策略模式
*/
interface clothesAction{
public function display();
}
class ShowBoyClothes implements clothesAction{
public function display(){
echo "There are many boy clothes<br>";
}
}
class ShowGirlClothes implements clothesAction{
public function display(){
echo "There are many girl clothes<br>";
}
}
class ShowPeopleClothes{
private $show;
public function showClothes(){
$this->show->display();
}
public function setClothes(clothesAction $clothes){
$this->show = $clothes;
}
}
class ShowPersonClothes extends ShowPeopleClothes{
}
// Test Case
$p = new ShowPersonClothes();
/* 設定男裝 */
$p->setClothes(new ShowBoyClothes());
$p->showClothes();
/* 設定女裝 */
$p->setClothes(new ShowGirlClothes());
$p->showClothes();
<?php
/*
介面卡模式
*/
//1、源
abstract class Toy
{
public abstract function openMouth();
public abstract function closeMouth();
}
class Dog extends Toy
{
public function openMouth()
{
echo "Dog open Mouth<br>";
}
public function closeMouth()
{
echo "Dog close Mouth<br>";
}
}
class Cat extends Toy
{
public function openMouth()
{
echo "Cat open Mouth<br>";
}
public function closeMouth()
{
echo "Cat close Mouth<br>";
}
}
//2、目標角色:紅棗遙控公司+綠棗遙控公司
interface RedTarget
{
public function doMouthOpen();
public function doMouthClose();
}
interface GreenTarget
{
public function operateMouth($type = 0);
}
//3、介面卡程式碼:紅棗遙控公司+綠棗遙控公司
class RedAdapter implements RedTarget
{
private $adaptee;
function __construct(Toy $adaptee)
{
$this->adaptee = $adaptee;
}
public function doMouthOpen()
{
$this->adaptee->openMouth();
}
public function doMouthClose()
{
$this->adaptee->closeMouth();
}
}
class GreenAdapter implements GreenTarget
{
private $adaptee;
function __construct(Toy $adaptee)
{
$this->adaptee = $adaptee;
}
public function operateMouth($type = 0)
{
if ($type) {
$this->adaptee->openMouth();
} else {
$this->adaptee->closeMouth();
}
}
}
//4、測試用例
class testDriver
{
public function run()
{
//例項化一隻狗玩具
$adaptee_dog = new Dog();
echo "給狗套上紅棗介面卡<br>";
$adapter_red = new RedAdapter($adaptee_dog);
//張嘴
$adapter_red->doMouthOpen();
//閉嘴
$adapter_red->doMouthClose();
echo "給狗套上綠棗介面卡<br>";
$adapter_green = new GreenAdapter($adaptee_dog);
//張嘴
$adapter_green->operateMouth(1);
//閉嘴
$adapter_green->operateMouth(0);
}
}
$test = new testDriver();
$test->run();
//結果:
// 給狗套上紅棗介面卡
// Dog open Mouth
// Dog close Mouth
// 給狗套上綠棗介面卡
// Dog open Mouth
// Dog close Mouth