策略模式按我個人的理解說就是將類中重覆使用的代碼分離出來形成一個策略類,其他類想要調用的話,首先在初始化的時候就要把這個策略類作為參數傳遞進來即形成一種組合關係,然後在類內部就可以直接調用這個策略類中的邏輯了。 簡單說一下類的組合與聚合關係(很長一段時間里對這種關係一直比較懵,代碼看多了,並查看了一 ...
策略模式按我個人的理解說就是將類中重覆使用的代碼分離出來形成一個策略類,其他類想要調用的話,首先在初始化的時候就要把這個策略類作為參數傳遞進來即形成一種組合關係,然後在類內部就可以直接調用這個策略類中的邏輯了。
簡單說一下類的組合與聚合關係(很長一段時間里對這種關係一直比較懵,代碼看多了,並查看了一些資料才稍微有些概念,這裡單獨拿出來說一下),類的組合關係類似一個人,人要是死了身體的各個器官就消亡了,這個器官可以理解成上述的策略類。需要調用這個策略類的類假如生命周期結束,那麼這個策略類的生命周期也就結束了,無法單獨存在使用。而聚合關係類似一臺電腦,這臺電腦要是壞了,電腦的部分部件還可以拿出來繼續使用(這種關係在看到組合模式的時候會有一個比較清楚的概念)。
現在來看書中(深入PHP面向對象模式與實踐)原文代碼,雖然書中說了與之前的解釋器模式的代碼有關聯,但可以不必理會,把它看成一個獨立的部分來理解就可以了。
//一個抽象基類,可以想象成一個人,而策略類就是人體上的器官
abstract class Question{
protected $prompt;
protected $marker; //策略類
function __construct ($prompt,Marker $marker){ //繼承他的類在初始化的時候將傳遞策略類進來
$this->marker = $marker;
$this->prompt = $prompt;
}
function mark($response){
return $this->marker->mark($response); //這裡它執行了策略類的邏輯
}
}
//下麵這個二個類繼承了Question他們分別有自己的業務邏輯,按原文的說法它們將分別處理用戶輸入的文本信息和多媒體信息
class TextQuestion extends Question{
//這裡原文也沒給什麼示例代碼,只說了自己想象他的業務邏輯。其實也不必太在意,畢竟主要是為了瞭解模式的概念。
}
class AVQuestion extends Question {
}
//以下的類就是策略類,假如上述的TextQuestion和AVQuestion類中有重覆的代碼就可以把這個代碼分離到這個策略類中
//為啥要分離呢,因為假如要擴展BVQuestion,CVQuestion類其中都重覆使用了一個方法(有相同或類似的業務邏輯)比如function mark($response)
//那麼每次擴展一個類都要使用function mark($response)時候都要複製粘貼,等要修改這個Mark方法的時候你就頭疼了
abstract class Marker{
protected $test;
function __construct ($test){
$this->test= $test;
}
//這裡定義了抽象方法mark,繼承他的類必須實現,也就是對於不同的用戶錄入信息需要不同的實現
abstract function mark($response);
}
class MarkLogicMarker extends Marker{
private $engine;
function mark($response){ //對於marklogic 語言需要進行的處理
return true;
}
}
class MatchMarker extends Marker{
function mark($response){
return ($this->test == $response); //對於簡單判斷用戶輸入是否等於某個值需要進行的處理
}
}
class RegexpMarker extends Marker{
function mark($response){
return (preg_match($this->test,$response)); //對於需要使用正則的用戶輸入進行的處理
}
}
//客戶端代碼
$markers = array(
new RegexpMarker("/f.ve/"), //這個定義上述的幾個策略類,在下麵的代碼中將分別使用這幾個策略類來進行測試
new MatchMarker("five"),
new MarkLogicMarker('$input equals "five"')
);
foreach ($markers as $marker){
print get_class($marker)."<br/>";
$question = new TextQuestion("how many beans make five",$marker);
foreach(array("five","four") as $response){ // 這裡的array("five","four")模擬了用戶的輸入信息
print "\tresponse: $response:";
if($question->mark($response)){
print "well done<br/>";
} else {
print "never mind<br/>";
}
}
}
複製粘貼一下上面的代碼運行一下看看結果吧!上面我說的可能都是廢話,自己直接運行代碼看看可能學習效果好的多。
最後:路漫漫其修遠兮 吾將上下而求索!