最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

第1章 面向?qū)ο笈c簡(jiǎn)單工廠

2023-09-01 17:31 作者:納西妲愛編程  | 我要投稿

第1章 ? ?面向?qū)ο笈c簡(jiǎn)單工廠

1.1 ? ?理解面向?qū)ο笕筇攸c(diǎn)

1.1.1 ? ?封裝

封裝的概念

封裝就是把客觀事物封裝成抽象的類,并且類可以把自己的數(shù)據(jù)和方法只讓可信的類或者對(duì)象操作,對(duì)不可信的進(jìn)行信息隱藏。

簡(jiǎn)單理解:就好比一臺(tái)筆記本電腦,它里面有cup ,網(wǎng)卡,顯卡,硬盤等配件。這些東西并不是直接暴露給用戶,而是提供一些按鈕供用戶使用這臺(tái)電腦。其中部分配件不希望用戶能夠直接看到或者修改,可以 ‘’封裝‘’ 起來。

封裝特性

在一個(gè)對(duì)象產(chǎn)生之后,對(duì)象的部分成員屬性和成員方法邏輯上是不允許在對(duì)象外部調(diào)用或者使用的。這就是封裝特性的由來。封裝關(guān)鍵字: private(私有的)。

比如有一個(gè) NotebookComputer 類,其中成員屬性 $cpu 和 成員方法 watchMovie() 是私有的。

<?php
class NotebookComputer
{
? ?//成員屬性
? ?var $color = '白色';
? ?var $brand = '外星人';
? ?private $cpu = '英特爾第11代';
? ?var $monitor = '8K 顯示器';

? ?function playGame()
? ?{
? ? ? ?echo '吃雞! LOL !';
? ?}

? ?private function watchMovie()
? ?{
? ? ? ?echo '看各種顏色的電影 !';
? ?}

}

$nc = new NotebookComputer();

var_dump($nc);
$nc->cpu;
//$nc->watchMovie();

在NotebookComputer 類的外部訪問該類的私有成員屬性和成員方法會(huì)報(bào)錯(cuò)。

代碼運(yùn)行結(jié)果


注意:

  1. 被 private 修飾的成員屬性不能夠在類的外部進(jìn)行訪問,可以在類的內(nèi)部訪問。

  2. 被 private 修飾的成員方法也不能夠在類的外部進(jìn)行訪問,可以在類的內(nèi)部進(jìn)行訪問。

  3. var 和 private 修飾關(guān)鍵字只能選取一個(gè)(包括公共的: public 關(guān)鍵字和受保護(hù)的:protected 關(guān)鍵字)。


這里我們可以使用魔術(shù)方法__get() 來開個(gè)可以訪問的后門,該方法在訪問私有成員屬性的時(shí)候會(huì)自動(dòng)觸發(fā)。

<?php
class NotebookComputer
{
? ?//成員屬性
? ?var $color = '白色';
? ?var $brand = '外星人';
? ?private $cpu = '英特爾第11代';
? ?var $monitor = '8K 顯示器';

? ?function playGame()
? ?{
? ? ? ?echo '吃雞! LOL !';
? ?}

? ?private function watchMovie()
? ?{
? ? ? ?echo '看各種顏色的電影 !';
? ?}
? ?// 添加魔術(shù)方法 __get(),該方法有一個(gè)參數(shù),該參數(shù)是屬性名稱
? ?function __get($pro)
? ?{
? ? ? return $this->$pro;
? ?}
}

$nc = new NotebookComputer();

var_dump($nc);

echo '<br/>';

echo $nc->cpu;

以上代碼運(yùn)行結(jié)果 :

代碼運(yùn)行結(jié)果


可以看到?jīng)]有報(bào)錯(cuò)并且訪問到了私有屬性 cpu。


注意:魔術(shù)方法 _get( )

  • 觸發(fā)時(shí)機(jī): 訪問私有成員屬性的時(shí)候自動(dòng)觸發(fā)。

  • 功能: 1. 為私有成員屬性訪問提供后門參數(shù)。 2. 屏蔽錯(cuò)誤。

  • 參數(shù): 1個(gè)。訪問的私有成員屬性名稱。

  • 返回值: 可有可無。


一個(gè)類的私有成員屬性是不能直接訪問和修改的。上面我們講到可以通過 __get()方法實(shí)現(xiàn)訪問私有屬性,那可不可以修改私有屬性呢?可以通過 __set 魔術(shù)方法來修改,該魔術(shù)方法是在設(shè)置(修改)成員屬性的時(shí)候會(huì)自動(dòng)觸發(fā)。

class Person
{
//成員屬性
? ?var $name = '李蓮英';
? ?private $sex = '男'; //私有屬性
? ?var $age = 38;

//成員方法
? ?function say()
? ?{
? ? ? ?echo '老佛爺吉祥';
? ?}

? ?function nn()
? ?{
? ? ? ?echo '嘩啦啦啦啦啦~~~';
? ?}
? ?// 添加一個(gè)魔術(shù)方法,該方法有兩個(gè)參數(shù)一個(gè)是私有屬性名,一個(gè)是私有屬性值。無返回值
? ?function __set($pro_name,$new_val)
? ?{
? ? ? //通過$new_val拿到新的屬性值:不男不女,給屬性(sex)賦值
? ? ? ?$this->$pro_name = $new_val;
? ?}

}

//實(shí)例化一個(gè)對(duì)象
$lly = new Person;
var_dump($lly);

//直接訪問私有成員屬性會(huì)報(bào)錯(cuò)
//echo $lly->sex;

//設(shè)置(修改)私有成員屬性
$lly->sex = '不男不女';

var_dump($lly);

以上代碼運(yùn)行結(jié)果 :

代碼運(yùn)行結(jié)果


可以看到給私有屬性 sex 重新賦值成功。

注意 :魔術(shù)方法 _set( )

  • 觸發(fā)時(shí)機(jī): 對(duì)私有成員屬性進(jìn)行設(shè)置值得時(shí)候自動(dòng)觸發(fā)。

  • 功能: 1. 為私有成員屬性設(shè)置值。 2. 屏蔽錯(cuò)誤。

  • 參數(shù): 2個(gè)。 第一個(gè)參數(shù)是私有成員屬性名。第二個(gè)參數(shù)是要設(shè)置的新值。

  • 返回值: 無。


1.1.2 ? ?繼承

繼承是指可以讓某個(gè)類型的對(duì)象獲得另一個(gè)類型的對(duì)象的屬性和方法。

繼承的語法格式 :

clas類名 extends 父類名 {
? //書寫子類獨(dú)有的方法和書寫
}

Father 類通過 extends 關(guān)鍵字繼承 GrandFather 代碼如下 :

<?php
//繼承特性
//爺爺類
class GrandFather{
? ?//成員屬性
? ?var $familyName = '曹';
? ?var $lastName;
? ?var $sex= '男';
? ?//成員方法
? ?function love()
? ?{
? ? ? ?echo '喜歡美女 ?。?!';
? ?}
? ?function drink()
? ?{
? ? ? ?echo '對(duì)酒當(dāng)歌 ?。?!';
? ?}
}
//父親類
class Father extends GrandFather{
? ?var $write = '7步成詩';
? ?function run()
? ?{
? ? ? ?echo '我在狂奔!??!';
? ?}
}
$fa = new Father();
var_dump($fa);

echo '<br/>';
$fa->drink();

以上代碼運(yùn)行結(jié)果 :

代碼運(yùn)行結(jié)果


從上面結(jié)果中可以看到,F(xiàn)ather 把 GrandFather 類中的屬性和方法繼承過來了,而且還可以有自己的屬性 $write 和方法 run( )

有些概念我們需要理解清楚 : 父類: 被其它類繼承的就是父類,也叫作基類。如上面案例中的:GrandFather 類。

子類: 繼承其他類的類就是子類,也叫作派生類。如上面案例中的:Father 類。


注意:

  1. 子類繼承父類既具備父類中所有的成員屬性和方法(私有的除外)。

  2. 子類繼承父類之后可以具有子類獨(dú)有的屬性和方法。

  3. 在繼承時(shí),子類中允許出現(xiàn)和父類同名的方法,這種情況不會(huì)沖突,而是子類的方法會(huì)覆蓋父類的方法,這種方式叫做重載(重新加載)。

  4. 魔術(shù)方法也可以被子類繼承。

  5. 如果父類具有構(gòu)造方法,子類也需要構(gòu)造方法進(jìn)行構(gòu)造成員屬性,此時(shí)需要在子類中重載父類的構(gòu)造方法,并且在構(gòu)造方法中使用 parent : : ___construct( ) 進(jìn)行調(diào)用父類的構(gòu)造方法,構(gòu)造繼承而來的父類的成員屬性。

  6. 繼承代碼的時(shí)候不要瞎繼承,人類不要繼承鳥類,不會(huì)變成鳥人。要有一定的邏輯關(guān)系。

  7. PHP 語言是單繼承,可以通過一些方式實(shí)現(xiàn)多繼承。如:trait 。


1.1.3 ? ?多態(tài)

多態(tài)就是指一個(gè)類實(shí)例的相同方法在不同情形有不同表現(xiàn)形式。多態(tài)機(jī)制使具有不同內(nèi)部結(jié)構(gòu)的對(duì)象可以共享相同的外部接口。這意味著,雖然針對(duì)不同對(duì)象的具體操作不同,但通過一個(gè)公共的類,它們(那些操作)可以通過相同的方式予以調(diào)用。

多態(tài)是一種思想,可以簡(jiǎn)單的理解為:不同的人做相同的事得到不同的結(jié)果。

案例代碼 :

<?php

//舉栗子:妹子相親,在相親過程中可能會(huì)遇到不同的人,有屌絲,有高富帥...

//妹子
class Girl{
? ?//約會(huì)方法
? ?function meet(Man $obj)
? ?{
? ? ? ?$obj->kiss();
? ?}
}

// 相親對(duì)象 漢子類
abstract class Man{
? ?// 必須實(shí)現(xiàn)kiss方法
? ?abstract public function kiss();
}

//屌絲類 ?繼承漢子類
class ?Loser extends Man{
? ?//屌絲類的獨(dú)有方法
? ?public function aa()
? ?{
? ? ? ?echo '美女我們 AA 制吧 !';
? ?}
? ?//必須實(shí)現(xiàn)的方法
? ?public function kiss()
? ?{
? ? ? ?echo '啪?。?!反手一巴掌!';
? ?}
}

//高富帥類 ?繼承漢子類
class ?Gfs extends Man{
? ?//高富帥類的獨(dú)有方法
? ?public function zj()
? ?{
? ? ? ?echo '獻(xiàn)上 999 克拉鉆戒 !';
? ?}
? ?//必須實(shí)現(xiàn)的方法
? ?public function kiss()
? ?{
? ? ? ?echo '么么噠?。?!愛你喲!';
? ?}
}

//實(shí)例化
//妹子
$girl = new Girl();

//相親對(duì)象
//屌絲
$loser = new Loser();
//高富帥
$gfs = new Gfs();

//開始相親
$girl->meet($loser);
echo '<br/>';
$girl->meet($gfs);

以上代碼運(yùn)行結(jié)結(jié)果 :

代碼運(yùn)行結(jié)果


從上面例子可以看出:不同的漢子在相親的時(shí)候,得到的結(jié)果是不同的。這種思想就是多態(tài),不同的人在做同一件事件得到不同的結(jié)果。


1.2 ? ?構(gòu)建計(jì)算器

前臺(tái)代碼實(shí)現(xiàn) :

<!DOCTYPE html>
<html lang="en">
<head>
? ?<meta charset="UTF-8">
? ?<title>計(jì)算器</title>
</head>
<body>
<form action="program.php" method="post">
? ?輸入數(shù)字A:<input type="text" name="numA" values=""><br>
? ?運(yùn)算符:<select name="strOperate" style="width: 160px">
<option value="+">+</option>
<option value="-">-</option>
<option value="*">x</option>
<option value="/">/</option>
? ?</select><br>
? ?輸入數(shù)字B:<input type="text" name="numB" values=""><br>
? ?<input type="submit" name="" value="提交">
</form>
</body>
</html>

后臺(tái)計(jì)算功能代碼實(shí)現(xiàn) :

class Program
{
? ? public function index()
? ? {
$numA ? ? ? = $_POST["numA"];
$numB ? ? ? = $_POST["numB"];
$strOperate = $_POST["strOperate"];
$strResult ?= "";
switch ($strOperate) {
? case '+':
? ? ? $strResult = $numA + $numB;
? ? break;
? case '-':
? ? ? $strResult = $numA - $numB;
? ? ? break;
? case '*':
? ? ? $strResult = $numA * $numB;
? ? break;
? case '/':
? ? ? $strResult = $numA / $numB;
? ? break;
}
echo "結(jié)果是".$strResult;
? ? }
}

在這里雖然功能實(shí)現(xiàn)了,但是這樣的代碼并不良好,如果我們?cè)陧?xiàng)目中另一個(gè)地方需要一個(gè)計(jì)算的功能,這個(gè)時(shí)候通常我們會(huì)選擇直接復(fù)制,但這不是一個(gè)好的編碼習(xí)慣,因?yàn)榇a中重復(fù)的代碼多到一定程度,維護(hù)時(shí),可能就是一個(gè)大的麻煩,編程有一原則,就是用盡可能的辦法去避免重復(fù)。

1.3 ? ?理解簡(jiǎn)單工廠模式

1. 什么是簡(jiǎn)單工廠模式?

簡(jiǎn)單工廠模式是屬于創(chuàng)建型模式,又叫做靜態(tài)工廠方法(Static Factory Method)模式,但不屬于 23 種 GOF設(shè)計(jì)模式之一。簡(jiǎn)單工廠模式是由一個(gè)工廠對(duì)象決定創(chuàng)建出哪一種產(chǎn)品類的實(shí)例。簡(jiǎn)單工廠模式是工廠模式家族中最簡(jiǎn)單實(shí)用的模式,可以理解為是不同工廠模式的一個(gè)特殊實(shí)現(xiàn)。

2. 簡(jiǎn)單工廠模式的特點(diǎn)

優(yōu)點(diǎn) :

工廠類是整個(gè)模式的關(guān)鍵.包含了必要的邏輯判斷,根據(jù)外界給定的信息,決定究竟應(yīng)該創(chuàng)建哪個(gè)具體類的對(duì)象.通過使用工廠類,外界可以從直接創(chuàng)建具體產(chǎn)品對(duì)象的尷尬局面擺脫出來,僅僅需要負(fù)責(zé)“消費(fèi)”對(duì)象就可以了。而不必管這些對(duì)象究竟如何創(chuàng)建及如何組織的.明確了各自的職責(zé)和權(quán)利,有利于整個(gè)軟件體系結(jié)構(gòu)的優(yōu)化。

缺點(diǎn) :

由于工廠類集中了所有實(shí)例的創(chuàng)建邏輯,違反了高內(nèi)聚責(zé)任分配原則,將全部創(chuàng)建邏輯集中到了一個(gè)工廠類中;它所能創(chuàng)建的類只能是事先考慮到的,如果需要添加新的類,則就需要改變工廠類了。

當(dāng)系統(tǒng)中的具體產(chǎn)品類不斷增多時(shí)候,可能會(huì)出現(xiàn)要求工廠類根據(jù)不同條件創(chuàng)建不同實(shí)例的需求.這種對(duì)條件的判斷和對(duì)具體產(chǎn)品類型的判斷交錯(cuò)在一起,很難避免模塊功能的蔓延,對(duì)系統(tǒng)的維護(hù)和擴(kuò)展非常不利;這些缺點(diǎn)在工廠方法模式中得到了一定的克服。

3. 使用場(chǎng)景

工廠類負(fù)責(zé)創(chuàng)建的對(duì)象比較少。

客戶只知道傳入工廠類的參數(shù),對(duì)于如何創(chuàng)建對(duì)象(邏輯)不關(guān)心。

由于簡(jiǎn)單工廠很容易違反高內(nèi)聚責(zé)任分配原則,因此一般只在很簡(jiǎn)單的情況下應(yīng)用。

1.4 ? ?運(yùn)用簡(jiǎn)單工廠模式重構(gòu)計(jì)算器

在這里就可以創(chuàng)建一個(gè) Operation 的計(jì)算類, 把計(jì)算的過程提取為計(jì)算類的方法 getResult ( ) 。

代碼如下所示 :

class Operation
{
? ? public static function getResult($numA, $numB, $strOperate)
? ? {
$strResult ?= "";
switch ($strOperate) {
? case '+':
? ? ? $strResult = $numA + $numB;
? ? break;
? case '-':
? ? ? $strResult = $numA - $numB;
? ? ? break;
? case '*':
? ? ? $strResult = $numA * $numB;
? ? break;
? case '/':
? ? ? $strResult = $numA / $numB;
? ? break;
}
return $strResult;
? ? }
}

客戶端代碼如下所示 :

class Client
{
? ? public function index()
? ? {
$numA ? ? ? = $_POST["numA"];
$numB ? ? ? = $_POST["numB"];
$strOperate = $_POST["strOperate"];
$operation ?= new Operation();
$strResult ?= $operation -> getResult($numA, $numB, $strOperate);
echo "結(jié)果是".$strResult;
? ? }
}

$client = new Client();
try {
? ?$client->index();
} catch (\Exception $e) {
? ?echo "你輸入的有誤".$e;
}

上面我們雖然有面向?qū)ο蟮奶匦裕侵挥玫搅艘粋€(gè)特點(diǎn)封裝,如果需求中需要增加一個(gè)開根 (sqrt) 運(yùn)算,這個(gè)時(shí)候我們就需要修改 operation 類在 switch 上加一個(gè)分支。但是卻需要讓加減乘除的運(yùn)算參與編譯,如果在這個(gè)修改過程中一不小心改錯(cuò)了某一項(xiàng)的計(jì)算這就會(huì)對(duì)整個(gè)系統(tǒng)帶來問題。在這里我們可以再把面向?qū)ο蟮牧硗鈨蓚€(gè)特點(diǎn)(繼承,多態(tài))加進(jìn)來。

工廠升級(jí) :

在這里把所有運(yùn)算方式看成為一個(gè)對(duì)象,把運(yùn)算看成為所有運(yùn)算方式的父類 Operation,這個(gè)類中有兩個(gè)屬性 $numA, $numB 代表的就是你要計(jì)算的值,同時(shí)可以提供一個(gè) get set 的方法對(duì)計(jì)算的值進(jìn)行獲取和賦值,getResult()為運(yùn)算方法,代碼如下所示 :

// 運(yùn)算類 的父類
abstract class Operation
{
? ?## 運(yùn)算類的兩個(gè)屬性
? ?protected $numA = 0;
? ?protected $numB = 0;
? ?## 分別提供一個(gè)get,set的方法對(duì)屬性的獲取和設(shè)置
? ?public function getNumA()
? ?{
? ? ?return $this->numA;
? ?}
? ?public function setNumA($numA = 0)
? ?{
? ? ?$this->numA = $numA;
? ?}
? ? ?public function getNumB()
? ?{
? ? ?return $this->numA;
? ?}
? ? ?public function setNumB($numB = 0)
? ?{
? ? ?$this->numB = $numB;
? ?}
? ? ?## 所有運(yùn)算子類所需要實(shí)現(xiàn)的運(yùn)算方法
? ? ?public abstract function getResult();
}

子類加法類,減法類,乘法類,除法類等等,繼承 Operation 運(yùn)算類,實(shí)現(xiàn)父類中的計(jì)算方法。

代碼如下所示 :

// 加法類
class OperationAdd extends Operation
{
? ?## 實(shí)現(xiàn)父類的計(jì)算方法
? ?public function GEtResult()
? ?{
? ? ?$result = $this->numA + $this->numB;
? ? ?return $result;
? ?}
}
// 減法類
class OperationSub extends Operation
{
? ?## 實(shí)現(xiàn)父類的計(jì)算方法
? ?public function GEtResult()
? ?{
? ? ?$result = $this->numA - $this->numB;
? ? ? return $result;
? ?}
}
// 乘法類
class OperationMul extends Operation
{
? ?## 實(shí)現(xiàn)父類的計(jì)算方法
? ?public function GEtResult()
? ?{
? ? ?$result = $this->numA * $this->numB;
? ? ?return $result;
? ?}
}
// 除法類
class OperationDiv extends Operation
{
? ?## 實(shí)現(xiàn)父類的計(jì)算方法
? ?public function GEtResult()
? ?{
? ? ?$result = $this->numA / $this->numB;
? ? ?return $result;
? ?}
}

簡(jiǎn)單工廠模式,也就是說到底要實(shí)例化誰,將來會(huì)不會(huì)增加實(shí)例化對(duì)象,比如增加開根運(yùn)算,這是很容易變化的地方,應(yīng)該考慮用一個(gè)單獨(dú)的類來創(chuàng)造實(shí)例的過程,這就是工廠 。

創(chuàng)建一個(gè)簡(jiǎn)單工廠類 operationFactory,根據(jù)對(duì)應(yīng)調(diào)用的方法創(chuàng)建對(duì)應(yīng)的工廠類 。

代碼如下所示 :

// 簡(jiǎn)單運(yùn)算工廠類
class OperationFactory
{
? ?## 根據(jù)需求創(chuàng)建對(duì)應(yīng)的工廠類
? ?public static function createOperate($operate)
? ?{
$oper = null;
switch ($operate) {
? ?case '+':
$oper = new OperationAdd();
break;
? ?case '-':
$oper = new OperationSub();
break;
? ?case '*':
$oper = new OperationMul();
break;
? ?case '/':
$oper = new OperationDiv();
break;
}
return $oper;
? ?}
}

客服端代碼如下所示 :

class Client
{
? ?public function index()
? ?{
$numA ? ? ? = $_POST["numA"];
$numB ? ? ? = $_POST["numB"];
$strOperate = $_POST["strOperate"];
## 創(chuàng)建對(duì)應(yīng)的計(jì)算類
$oper = OperationFactory::createOperate($strOperate);
$oper->setNumA($numA);
$oper->setNumB($numB);
$strResult = $oper->GEtResult();
echo "結(jié)果是".$strResult;
? ?}
}
$client = new Client();
try {
? ?$client->index();
} catch (\Exception $e) {
? ?echo "你輸入的有誤".$e;
}

這樣我們?cè)谔砑有碌乃惴ǖ臅r(shí)候只需創(chuàng)建一個(gè)對(duì)應(yīng)的運(yùn)算方法的類,同時(shí)修改 switch 即可,這樣就避免去操作過程中修改了其他的算法。

結(jié)果,如下圖所示 :


第1章 面向?qū)ο笈c簡(jiǎn)單工廠的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
玉树县| 泰安市| 博客| 屯昌县| 凌云县| 通海县| 桐乡市| 宝应县| 鹿泉市| 牙克石市| 九江县| 德清县| 平谷区| 桦甸市| 高邮市| 孝感市| 张家口市| 安多县| 新泰市| 三原县| 东平县| 贞丰县| 香河县| 东丽区| 麦盖提县| 平安县| 延川县| 岐山县| 长岭县| 定兴县| 高州市| 莎车县| 定结县| 昌图县| 斗六市| 蒲江县| 寻甸| 巴中市| 麦盖提县| 贵南县| 邻水|