麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 開發 > PHP > 正文

深入php面向對象、模式與實踐

2024-05-04 23:43:09
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了深入php面向對象、模式與實踐,需要的朋友可以參考下
 

1 語法

1.1 基礎語法

clone

需要操作原對象,但又不想影響原對象.

 

復制代碼代碼如下:

$K_back = clone $K;

 

基本數據類型和數組都為真復制,即為真副本,當屬性為對象時,為假復制,改變副本仍會影響原對象.解決方案:

//在原對象中添加function __clone(){  $this->對象 = clone $this->對象} 

__clone在clone前自動觸發,可以執行一些在備份前的屬性操作.

2、&傳遞引用

方法引用傳遞,改變源對象

 

復制代碼代碼如下:

function set_K(& $K){...}
function & get_K(){...}

 

3、static延遲靜態綁定

應用場景:Dog類和Person類都需要一個返回實例化的方法,Dog類和Person類都繼承于Animal抽象類.

abstract class Animal{  public static function create(){    //實例化調用類    return new static();  }}class Person extends Animal{...}//返回Person實例化類Person::create();

4、攔截器

__get($property),訪問未定義的屬性時調用.
__set($property,$value),給未定義的屬性賦值時被調用.
__isset($property),對未定義屬性調用isset()方法時調用.
__unset($property),對未定義屬性調用unset()方法時調用.
__call($method,$arg_array),調用未定義方法時調用.
__call很有用,但要慎用,因為太靈活.
應用場景:有一個專門打印Person類信息的Person_Writer類,如果通過Person類調用Person_Writer類.

//Person委托Person_Writer類處理打印事務.class Person {  private $writer;  ...  function __call($method_name,$args){    if(methood_exists($this->wirter,$method_name)){      return $this->writer->method_name($this);    }  }  //高級__call寫法,當委托方法參數不確定時使用.  function __call($method_name,$args){    //當然這里這樣寫法意義不大,但是call一般都是用call_user_func_array調用    $args = $this ;    if(methood_exists($this->wirter,$method_name)){      return call_user_func_array(        array($this->writer,$method_name),$args);      )    }  }} 

5、回調函數

應用場景: 3個類,Product類,Product_Sale類,Product_Totalizer類,要實現:當賣出Product總共價格超過指定金額時,輸出警告.

//Productclass Product {  public $name;  public $price;}//Product_Saleclass Product_Sale {  private $callbacks;  //記錄回調函數  function register_callback ($callback) {    if(! is_callback($callback)){      thow new Exception('callback not callable');    }    $this->callbacks[] = $callback;  }  //執行回調函數  function sale ($product){    print "{$product->name} : 處理中 /n";    foreach($this->callbacks as $callback){      call_user_func($callback , $product);    }  }}//Produce_Totalizerclass Produce_Totalizer {  static function warn_amount ($amt) {    $count = 0;    return function ($produce) use ($amt , &count) {      $count += $produce->price;      print " count : {count}/n"      if($count>$amt){        print "超過指定金額{$amt}啦~";      }    };  }}//模擬場景$product_sale = new Produce_Sale();//指定報警金額為8塊$product_sale = register_callback(Produce_Totalizer::warn_amount(8)); //賣商品$product_sale->sale(new Product("Durex",6));$product_sale->sale(new Produce("Jissbon",5));//輸出結果Durex : 處理中  count :6 Jissbon : 處理中   count: 11超過指定金額8塊啦~

6、get_class()和instanceof

get_class(類)用于判斷是否精準等于類名;

instanceof 可以判斷是否其本身或繼承于某父類.

7、類中的方法和類中的屬性

 

復制代碼代碼如下:

get_class_methods('類名'):獲取類中所有方法.
get_class_vars('類名'):獲取類中所有public參數;

 

8、反射API

2 模式

2.1 組合

問題:課堂類被演講類和研討會類繼承著.但是演講類和研討類都要實現一次性計費和上N次課計費的方法.和輸出計算的方式.

解決方案1: 在課堂類中添加計算一次性付費的方法,上N次課的計費方法和輸出計算方式的方法.

解決方案2: 運用組合,將處理計費和輸出計算方式單獨封裝為一個計費策略類.

深入php面向對象、模式與實踐

abstract class Cost_Strategy {  protected $duration;  abstract function cost ();  abstract function charge_type();  public __construct($duration){    $this->duration = $duration;  }}class Timed_Const_Strategy extends Cost_Stratedy {  function cost () {    //上一次課給5塊錢- -.    return $this->duration * 5;  }  function charge_type(){    return "多次課結算";  }}class Fixed_Const_Strategy extends Cost_Stratedy {  function cost (){    return 30 ;  }  function charge_type(){    return "一次性課結算";  }}abstract class Leason {  private $cost_strategy;  public __construct(Const_Strategy $cost_strategy){    $this->cost_strategy = $cost_strategy;  }  function __call($method_name,$args){    $args = $cost_strategy ;    if(methood_exists($this->cost_strategy,$method_name)){      return call_user_func_array(        array($this->writer,$method_name),$args);      )    }  }}//運用$leasons[] = new Seminar(new Timed_Const_Strategy(4));$leasons[] = new Lecture(new Fixed_Const_Strategy(null));foreach ($leasons as $leason){  print "leason charge : {$leason->const()}";  print "charge_type : {$leason->charge_type()}"}leason charge 20. charge_type : 多次課結算;leason charge 30. charge_type : 一次課結算;

組合既委托.同級委托.

繼承既父子關系.

3 生成對象
3.1 單例模式

確保系統中只有唯一一個用例.例如系統配置文件.

重點

1: 構造方法私有.

2: 類本身包含自己的實例化屬性.

深入php面向對象、模式與實踐

class Preferences {  private static $instance;  private function __construct(){ ... }  public static function get_instance(){    if(empty(self::$instance)){      self::$instance = new Preferences();    }    return self::$instance;  }  ...}//使用$preferences = Preferences::get_instance();

3.2 工廠模式

通過一個父類,生產處多個不同功能的子類.

特點:產品方(新浪微博)和需求方(顯示新浪微博)一一對應.

問題:印象筆記中,來源可能為新浪微博,或者開發者頭條,在印象筆記顯示的時候,兩者的頁眉和頁尾是不一樣的.

深入php面向對象、模式與實踐

3.3 抽象模式

RLGL!!!.印象筆記不只要顯示新浪微博內容!!!還要顯示我的新浪賬號,還要該微博啊!!臥槽~憋著急,吻我.

工廠模式主要用于生產一一對應的產品方和需求方,而抽象模式要做的是一個需求方(印象筆記_顯示新浪微博),要多個工廠(把需求方抽象為多個需求方),例如提供新浪內容的工廠,提供新浪賬號的工廠.提供微博內容的評論的工廠等.

深入php面向對象、模式與實踐

代碼:

abstract class Show_Evernote {  abstract function get_header_text();  abstract function get_context();  abstract function get_footer_text();  abstract function get_user();  abstract function get_comment();}class 顯示新浪微博 extends Show_Evernote{  function get_header_text(){...};  function get_context(){new 新浪微博_內容;}  function get_footer_text(){...};  function get_user(){new 新浪微博_賬號 ;}  function get_comment(){new 新浪微博_評論;}}//使用印象筆記控件類->內容 = 顯示新浪微博->get_context;印象筆記控件類->賬號 = 顯示新浪微博->get_context;...

3.4 平行模式

當使用工廠/抽象模式必須要制定具體的創建者(需求方).

平行模式和抽象模式的模型圖一致,但代碼實現不一樣.

抽象模式中父類均為抽象類,而平行模式中,所以類都為普通類,方便父類的實例化.

在這里列出顯示印象筆記類的實現代碼

class Show_Evernote{  private $內容;  private $賬號;  private $評論;  function __construct(內容,賬號,評論){    $this->內容 = 內容;    $this->賬號 = 賬號;    $this->評論 = 評論;  }  function get_內容(){    return clone $this->內容);  }  function get_賬號(){    return clone $this->賬號);  }  function get_評論(){    return clone $this->評論;  }}//使用$factory = new Show_Evernote(   new 新浪微博內容(),  new 新浪微博賬號(),  new 新浪微博評論());印象筆記控件類->顯示印象筆記 = $factory;

其實大家可以發現,原型模式只不過只在最頂層類中包裝了一下各組件子類而已,然而這樣可以輕松的組合他們,例如實現一個顯示新浪微博內容,但要顯示開發者頭條賬號的需求?

4 使用對象
4.1 組合模式

組合模式,可以理解為單一對象管理組合對象(聚合組件),最終組合體下的各個組合部件最好類型一致.不然特殊性越多,需要判斷就越多.

假設捶背男,洗腳男,洗發男,用來服務一個人(妹子).

假設妹子的幾個部位可用的服務男均為無限個.

深入php面向對象、模式與實踐

//創建一個妹子$妹子 = new 人();//添加洗腳男、捶背男$妹子->add_man(new 洗腳男);$妹子->add_man(new 捶背男);//循環所有男的給予舒服的方法.$妹子->計算舒服程度();

這是一個很理想的組合模式,在現實情況,我們使用組合模式,可能不得不創建多種類型的洗腳男,需要添加許多判斷條件.

4.2 裝飾模式

裝飾模式,首先洗腳男,洗發男,捶背男都是人,但是如果,一個男的又捶背,又洗發,這怎么玩?.add_man兩次?這不科學吧,來給這些男的裝飾一下吧~

深入php面向對象、模式與實踐

abstract class 人{  ...  abstract function get_well();}  class 男 extends 人 {  //無論你是神馬男,服務你,你就能獲得10點舒服度.  private $well = 10;  function get_well(){    return $this->well();  }}abstract class 裝飾男類型 extends 人 {  protected $人;  function __construct(人 $人){    $this->人 = $人;  } }class 捶背裝飾 extends 類型男裝飾{  function get_well(){    return $this->人->get_well()+30;  }}class 洗發裝飾 extends 類型男裝飾{  function get_well(){    return $this->人->get_well()+20;  }}class 洗褪裝飾 extends 類型男裝飾{  //老子不喜歡別人碰我的毛褲.  function get_well(){    return $this->人->get_well()-20;  }}//創建捶背,能給予的舒服指數 - -嘻嘻.$人 = new 捶背裝飾(new 男);$人->get_well(); // 10+30 = 40//來來來,全能選手,捶背、洗發、洗腿一起來$人 = new 洗腳裝飾(new 洗發裝飾(new 捶背裝飾(new 男()))); //10+30+20-20 = 40,注意順序,由里到外執行.

裝飾模式,既(組合+繼承),基類方法一定要盡量少,不然子類可能有它不該有的方法.直接類繼承,她只可能是一種形態,而她的多種形態可能一并擁有的時候,應該運用組合.

繼承即單一多態,組合既多種多態.

這個例子中,你可以添加女,然后把裝飾男類型改為裝飾通用類型,但每個get_well()都要多一個判斷是男還是女(如果給予的舒服程度不一樣).

這只是確保不可能出現在男,女之外的第三種人,如果基類為動物,給予服務的可能是雞,鵝,鴨,那么裝飾類型應該運用工廠模式,動物形態和裝飾形態一一對應.方便拓展.

除了服務類型,服務男的樣子也很重要,這就多了一種裝飾,現在有裝飾男類型和相貌男類型,這種情況怎么破,其實類似.深入php面向對象、模式與實踐

 

復制代碼代碼如下:

//如何獲取捶背的帥哥麥?,
$人 =new 男類型(new 捶背(new 帥哥麥(new 男())));

 

4.3 外觀模式

即給外部系統提供清晰接口

例如當Model層寫得很混亂,但是里面的方法還能用,那我們的Controller層應該列舉一些清晰的訪問方法來供View層訪問.外觀模式,強調的是清晰的訪問接口.

5 執行任務
5.1 策略模式

給類添加功能.對象要顯式的調用它.

繼續剛才的洗腳男和人的故事吧...你丫的爽完了要給錢吧?支付寶?微信?現金?

這個付款方式有多種,實現方法不應該放在人類中,而是應該委托給別的類

abstract class 人 {  protectd $支付方式;  function set_支付方式(){...}  function 付款(金額){    return $支付方式->付款($金額);  }}abstract class 付款{  abstract function 付款($金額);}class 支付寶付款 extends 付款{  function 付款($金額){    return 外接支付寶付款流程($金額);  }}...//使用$男 =new 男();///爽爽爽...//結賬$支付寶支付賬單 = new 支付寶付款($金額);$人 = new 男();$人->set_支付方式(new 支付寶付款());$人->付款();

5.2 觀察者模式

當被觀察者發生變化,觀察者需要被通知.

當數據發生變化,頁面需要被通知.

使用步驟:

觀察者加載到被觀察者中.
被觀察者通知觀察者.

深入php面向對象、模式與實踐

例如登陸類(被觀察)狀態改變,要出發郵件系統和日志系統(觀察者)

interface 被觀察者{  function attach(觀察者);  function detatch(觀察者);  function notify();}class Login implements 被觀察者{  private $觀察者;  function __construct(){    $this->觀察者 = array();  }  function attach($觀察者){    $this->觀察者 = $觀察者;   }  function detach($觀察者){    //刪除某個觀察者的操作;  }  function notify(){    foreach ($this->觀察者 as $單個觀察者){      $單個觀察者->update($this);    }  }    }interface 觀察者{  function update(被觀察者);}abstract class Login_觀察者 implements 觀察者{  private $login;  function __construct (Login $login){    $this->login = $login;    $login->attach($this);  }  function update(觀察者 $觀察者){    if ($觀察者 ===$this->login){      $this->do_update($觀察者);    }  }  abstract function do_update(Login $login);}class 郵件觀察者 extends 登陸觀察者 {  function do_update(Login $login){    //判斷條件 發送郵件  }}class 日志觀察者 extends 登陸觀察者 {  function do_update(Login $login){    //判斷條件 記錄到日志;  }}//使用$login = new Login();new 郵件觀察者 ($login);new 日志觀察者 ($login);

PHP有內置的SPL實現上述的觀察者模式.

5.3 訪問者模式

問題: 在一個軍隊中,有很多軍隊,軍隊下面可能包含軍隊/步兵/弓箭手,這時我們要顯示一個軍隊的戰斗力/需要糧食的各級分配?(遍歷對象并設置顯示方法).怎么辦?.解決辦法是軍隊還是保存自己的基本信息,設置一個訪問者,訪問者包含總戰斗力方法和總糧食的方法.

深入php面向對象、模式與實踐

訪問者

abstract class 軍隊訪問者{  abstract function 訪問(單元);  function 訪問軍隊($軍隊){     $this->訪問($軍隊);  }  function 訪問弓箭手($弓箭手){    $this->訪問($弓箭手);  }  //這里重復定義了大量代碼,其實可以用call來替代  function __call($method_name,$args){    if(strrpos($method_name, "訪問")){      return call_user_func_array(        array($this,"訪問"),$args      );    }  }}class 軍隊戰斗力訪問者 extends 軍隊訪問者{  private $text="";  function 訪問($單元){    $ret = "";    $pad = 4*$單元->getDpth(); //設置顯示深一級前面多4個空格.    $ret .= sprintf( "%{$pad}s","");    $ret .= get_class($單元). ": ";    $ret .= "戰斗力: " .$單元->bombardStrenth()."/n";    $this->text .=$ret;  }  function get_text(){    return $this->text;  }}

被訪問者

abstract class 單元{  function 接受($軍隊訪問者){    $method = "訪問_".get_class($this);    $軍隊訪問者->$method($this);  }  private $depth;  protected function set_depath($depth){    $this->depth=$depth;  }  function get_depth(){    return $this->depth;  }  ...}abstract class 綜合單元 extends 單元{  function 接受($軍隊訪問者){    parent::接受($軍隊訪問者)    foreach($this->單元集合 as $this_unit){      $this->unit->接受($軍隊訪問者);    }  }}class 軍隊 extends 綜合單元{  function bombardStrenth(){    $ret =0;    foreach($this-units() as $unit){      $ret += $unit->bombardStrenth();    }    return $ret  }}class 弓箭手 extends 單元{  function bombardStrenth(){    return 4;  }}

調用

$main_army = new Army();$main_army->add_unit(new 步兵());$main_army->add_unit(new 弓箭手());$軍隊戰斗力訪問者_實例 =new 軍隊戰斗力訪問者();$main_army->接受(均分戰斗力訪問者);print $軍隊戰斗力訪問者->get_text();

輸出

 

復制代碼代碼如下:

軍隊: 戰斗力: 50
    步兵: 攻擊力 :48
    弓箭手: 攻擊力: 4

 

5.4 命令模式

例子為Web頁面的login和feed_back,假如都需要使用ajax提交,那么問題來了,將表單封裝好提交上去,得到了返回結果.如何根據返回結果跳轉不同的頁面?.

有些同學就說了,login和feed_back各自寫一個方法憋,提交的時候調用各自的方法.

然后再來個logout命令..增加..刪除..命令怎么辦..

命令模式比較適合命令執行例如登陸,反饋等簡單只需要判斷是否成功的任務

深入php面向對象、模式與實踐

命令:

abstract class Command{  abstract function execute(Conmmand_Context $context);}class Login_Command extends Command{  function execute(CommandContext $context){    $managr =Register::getAccessManager();    $user = $context->get("username");    $pass = $context->get('pass');    $user_obj = $manager->login($user,$pass);    if(is_null($user_obj)){      $context->setError($manager->getError());      return false;    }    $context->addParam("user",$user_obj);    return true;  }}

部署命令的調用者

class Command_Facotry{  public function get_command($action){    $class = UCFirst(strtolower($action))."_Command";    $cmd = new $class();    return $cmd;  }}

客戶端

class Controller{  private $context;  function __construct(){    //Command_Context主要用來存儲request和params    $this->context =new Command_Context();  }  function process(){    $cmd Command_Factory::get_commad($this->context->get('action'));    if(!$cmd-execute($this->context)){      //錯誤處理    }else{      //成功 分發視圖    }  }}

使用

$controller =new Controller();$context = $controller->get_context();$context->add_param('action','login');$context->add_param('username','404_k');$context->add_param('pass','123456');$controller->process();


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 精品亚洲在线 | www.成人免费视频 | 私库av在线免费观看 | 粉色视频污 | 精品国产一区二区三区久久久 | 国产成人精品区一区二区不卡 | 色阁阁69婷婷 | 欧美a区 | 亚洲欧洲日韩av | 欧美精品久久久久久久久老牛影院 | 精品久久久久久久久久久久久久 | 在线观看国产一区二区三区 | 黄色日韩网站 | 久久精品国产清自在天天线 | 精品国产91久久久久久久 | 久久久久久久九九九九 | 午夜小视频免费观看 | chinese18 xxxx videos| 国产大片全部免费看 | 精品国产一区二区三区久久久 | 操操日日 | 中文字幕一二区 | 欧美视频国产精品 | 一区二区三区在线观看av | 欧美女孩videos| 国产91九色在线播放 | 精品国产一区二区亚洲人成毛片 | 一级电影在线观看 | av成人免费观看 | 国产日韩a | 美女擦逼 | 夜夜夜影院| xxxxhd86日本护士hd | jizzjizzjizzjizz国产 | 美女喷水网站 | 毛片免费观看视频 | 国内久久久久 | 日本高清一级片 | 欧美一级免费看 | 成人性爱视频在线观看 | 青青草免费观看 |