设计模式 重点版
創建型: 2 個 (工廠模式, 單例模式)
結構型: 6 個 (適配器模式, 組合模式, 裝飾者模式, 代理模式, 外觀模式, 橋梁模式)
行為型: 8 個 (中介者模式, 策略模式, 模板模式, 觀察者模式, 迭代器模式, 責任鏈模式, 命令模式, 狀態模式)
?
1. 工廠模式
提供一個創建類的統一接口.
目的: 每次創建類時, 只需要調用這個接口就可以了, 不用每次都需要寫一次創建代碼
?
2. 單例模式
保證在內存中一個類只有一個實例存在
目的: 例如一個系統中可能存在多個打印任務, 但是只能一個正在工作的打印任務在內存中.
?
3. 適配器模式
將一個類的接口轉換成客戶希望的另一個接口.
目的: 比如我們去別的地方, 我們的插座的方向頭是不一樣的, 比如(中國, 德國 我出差去德國), 適配器需要滿足以下要求:
(1) 必須符合德國標準的接口,否則的話還是沒辦法插到德國插座中
(2) 在調用上面實現的德標接口進行充電時,提供一種機制,將這個調用轉到對國標接口的調用
這就要求:
(1) 適配器必須實現原有的舊的接口
(2) 適配器對象中持有對新接口的引用,當調用舊接口時,將這個調用委托給實現新接口的對象來處理,也就是在適配器對象中組合一個新接口
?
4. 組合模式
將對象組合成樹型結構以表示“部分---整體”的層次結構
組合模式類似 “樹”
component: 組合中對象的接口聲明
composite: 樹枝結點(有子節點)
leaf: 樹葉結點(無子節點)
目的: 就是你想要這種層次關系的類時, 就可以使用.
例如: 各部門之間的層級關系
?
?各部門之間層級關系?
5. 裝飾者模式
動態的給一個對象添加一些額外的職責
目的: 需要擴展一個類的功能, 或給一個類增加額外的功能, 例如: 比如生日蛋糕, 有一些級別的蛋糕的情況, 比如, 巧克力蛋糕, 草莓蛋糕等, 但是, 要想在蛋糕上單獨加一些東西, 比如加一些花, 等等, 這樣, 就可以將基本的蛋糕采用繼承關系, 而裝飾者有個抽象類, 那些加的花啊什么的, 都是繼承這個裝飾者類, 參考下邊類圖
?
6. 代理模式
為其他對象提供一種代理以控制對這個對象的訪問
目的: 對對象訪問進行控制, 比如西門慶找潘金蓮,那潘金蓮不好意思答復呀,咋辦,找那個王婆做代理,表現在程序上時是這樣的體現的
代碼如下:
package com.yangguangfu.proxy; /** * * @author 阿福(trygf521@126.com)<br> *定義一種類型的女人,王婆和潘金蓮都屬于這個類型的女人 */ public interface KindWoman {//這種女人能做什么事情呢?public void makeEyesWithMan();//拋媚眼public void happyWithMan();//和男人那個....} 一種類型嘛,那肯定是接口,定義個潘金蓮 package com.yangguangfu.proxy; /** * * @author 阿福(trygf521@126.com)<br> *定義一個潘金蓮是什么樣的人 */ public class PanJinLian implements KindWoman{@Overridepublic void happyWithMan() {System.out.println("潘金蓮和男人在做那個...");}@Overridepublic void makeEyesWithMan() {System.out.println("潘金蓮拋媚眼...");}} 再定義個丑陋的王婆 package com.yangguangfu.proxy; /** * * @author 阿福(trygf521@126.com)<br> *王婆這個人老聰明了,她太老了,是個男人都看不上她, *但是她有智慧經驗呀,他作為一類女人的代理! */ public class WangPo implements KindWoman {private KindWoman kindWoman;public WangPo(){//默認的話是潘金蓮的代理this.kindWoman = new PanJinLian();}//她可以是KindWomam的任何一個女人的代理,只要你是這一類型public WangPo(KindWoman kindWoman){this.kindWoman = kindWoman;}@Overridepublic void happyWithMan() {//自己老了,干不了了,但可以叫年輕的代替。this.kindWoman.happyWithMan();}@Overridepublic void makeEyesWithMan() {//王婆年紀大了,誰看她拋媚眼啊this.kindWoman.makeEyesWithMan();}} 兩個女主角都上場了,該男主角了,定義個西門慶 package com.yangguangfu.proxy; /** * * @author 阿福(trygf521@126.com)<br> *水滸傳是這樣寫的:西門慶被潘金蓮用竹竿敲了一下,西門慶看癡迷了,被王婆看到了,就開始撮合兩人好事,王婆作為潘金蓮的代理人收了不少好處費,那我們假設一下: *如果沒有王婆在中間牽線,這兩個不要臉的能成事嗎?難說得很! */ public class XiMenQiang {/** * @param args */public static void main(String[] args) {WangPo wangPo;//把王婆叫出來wangPo = new WangPo();//然后西門慶說,我要和潘金蓮Happy,然后王婆就安排了西門慶丟筷子哪出戲:wangPo.makeEyesWithMan();//看到沒有表面是王婆在做,其實爽的是潘金蓮wangPo.happyWithMan();}}
?
7. 外觀模式
為子系統中的一組接口提供一個一致的界面
比如: 不知道大家有沒有比較過自己泡茶和去茶館喝茶的區別,如果是自己泡茶需要自行準備茶葉、茶具和開水,如圖1(A)所示,而去茶館喝茶,最簡單的方式就是跟茶館服務員說想要一杯什么樣的茶,是鐵觀音、碧螺春還是西湖龍井?正因為茶館有服務員,顧客無須直接和茶葉、茶具、開水等交互,整個泡茶過程由服務員來完成,顧客只需與服務員交互即可,整個過程非常簡單省事,如圖1(B)所示
在軟件開發中,有時候為了完成一項較為復雜的功能,一個客戶類需要和多個業務類交互,而這些需要交互的業務類經常會作為一個整體出現,由于涉及到的類比較多,導致使用時代碼較為復雜,此時,特別需要一個類似服務員一樣的角色,由它來負責和多個業務類進行交互,而客戶類只需與該類交互。外觀模式通過引入一個新的外觀類(Facade)來實現該功能,外觀類充當了軟件系統中的“服務員”,它為多個業務類的調用提供了一個統一的入口,簡化了類與類之間的交互。在外觀模式中,那些需要交互的業務類被稱為子系統(Subsystem)。如果沒有外觀類,那么每個客戶類需要和多個子系統之間進行復雜的交互,系統的耦合度將很大,如圖2(A)所示;而引入外觀類之后,客戶類只需要直接與外觀類交互,客戶類與子系統之間原有的復雜引用關系由外觀類來實現,從而降低了系統的耦合度,如圖2(B)所示。
?
8. 橋梁模式
橋梁模式將抽象部分與它的實現部分分離
目的: 比如我們有一個畫圖程序 有2個圖形(Circle Rectangle )和2種畫圖方法(Drawing1 Drawing2)圖形可能會使用Drawing1來畫圖 也可能使用Drawing2來畫圖在這個畫圖程序中有兩個可變因素 一個是圖形的種類 有可能會增加新的圖形 另一個是畫圖方法 可能會有Drawing3出現.
?
9. 中介者模式
中介者模式用一個中介對象封裝一系列的對象交互
目的: 比如 在生活中,當電腦缺少了一塊主板,那會怎么樣?如果有人這樣問我的話,我就會馬上跳出來說“這電腦肯定報廢了”,當然這不是重點。假如少了主板電腦還可以用的話,想想,里面的CPU、顯卡、聲卡、光驅、硬盤等等,不是就要我們自己用線把它們連起來。想想就覺得頭疼,那么現在你覺得主板在電腦里扮演著什么角色呢?
例2:
Mediator:中介者接口。在里面定義了各個同事之間相互交互所需要的方法,可以是公共的方法,如Change方法,也可以是小范圍的交互方法
ConcreteMediator:具體的中介者實現對象。它需要了解并為維護每個同事對象,并負責具體的協調各個同事對象的交互關系。
Colleague:同事類的定義,通常實現成為抽象類,主要負責約束同事對象的類型,并實現一些具體同事類之間的公共功能,比如,每個具體同事類都應該知道中介者對象,也就是每個同事對象都會持有中介者對象的引用,這個功能可定義在這個類中。
ConcreteColleague:具體的同事類,實現自己的業務,需要與其他同事對象交互時,就通知中介對象,中介對象會負責后續的交互。
?
10. 策略模式
策略模式定義一系列的算法,把它們一個個封裝起來,并且使它們可以相互替換
比如:
劉備要到江東娶老婆了,走之前諸葛亮給趙云(伴郎)三個錦囊妙計,說是按天機拆開能解決棘手問題,嘿,還別說,真解決了大問題,搞到最后是周瑜陪了夫人又折兵,那咱們先看看這個場景是什么樣子的。
先說說這個場景中的要素:三個妙計,一個錦囊,一個趙云,妙計是亮哥給的,妙計放在錦囊里,俗稱就是錦囊妙計嘛,那趙云就是一個干活的人,從錦囊取出妙計,執行,然后獲勝。用java程序怎么表現這些呢?
那我們先來看看圖
三個妙計是同一類型的東西,那咱就寫個接口:
package com.yangguangfu.strategy; /** * * @author trygf521@126.com:阿福 * 首先定義一個策略接口,這是諸葛亮老人家給趙云的三個錦囊妙計的接口。 */ public interface IStrategy {//每個錦囊妙計都是一個可執行的算法。public void operate();}然后再寫三個實現類,有三個妙計嘛:
妙計一:初到吳國:
package com.yangguangfu.strategy; /** * * @author trygf521@126.com:阿福 * 找喬國老幫忙,使孫權不能殺劉備。 */ public class BackDoor implements IStrategy {@Overridepublic void operate() {System.out.println("找喬國老幫忙,讓吳國太給孫權施加壓力,使孫權不能殺劉備...");}}妙計二:求吳國太開個綠燈,放行:
package com.yangguangfu.strategy; /** * * @author trygf521@126.com:阿福 * 求吳國太開個綠燈。 */ public class GivenGreenLight implements IStrategy {@Overridepublic void operate() {System.out.println("求吳國太開個綠燈,放行!");}}妙計三:孫夫人斷后,擋住追兵:
package com.yangguangfu.strategy; /** * * @author trygf521@126.com:阿福 * 孫夫人斷后,擋住追兵。 */ public class BlackEnemy implements IStrategy {@Overridepublic void operate() {System.out.println("孫夫人斷后,擋住追兵...");}} 好了,大家看看,三個妙計是有了,那需要有個地方放妙計啊,放錦囊里: package com.yangguangfu.strategy; /** * * @author trygf521@126.com:阿福 * */ public class Context {private IStrategy strategy;//構造函數,要你使用哪個妙計public Context(IStrategy strategy){this.strategy = strategy;}public void operate(){this.strategy.operate();}} 然后就是趙云雄赳赳的揣著三個錦囊,拉著已步入老年行列,還想著娶純情少女的,色咪咪的劉備老爺子去入贅了,嗨,還別說,亮哥的三個妙計還真不錯,瞧瞧: package com.yangguangfu.strategy;public class ZhaoYun {/** * 趙云出場了,他根據諸葛亮給他的交代,依次拆開妙計 */public static void main(String[] args) {Context context;//剛到吳國的時候拆開第一個System.out.println("----------剛剛到吳國的時候拆開第一個---------------");context = new Context(new BackDoor());context.operate();//拆開執行System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n");//當劉備樂不思蜀時,拆開第二個System.out.println("----------劉備樂不思蜀,拆第二個了---------------");context = new Context(new GivenGreenLight());context.operate();//拆開執行System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n");//孫權的小追兵了,咋辦?拆開第三個錦囊System.out.println("----------孫權的小追兵了,咋辦?拆開第三個錦囊---------------");context = new Context(new BlackEnemy());context.operate();//拆開執行System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n");}} ?11. 模板模式
定義一個操作中的算法骨架, 而將一些步驟延遲到子類中
個人感覺是定義一套流程”即算法骨架”, 置于骨架的內容, 要到實現時, 會有不同
比如: 我們使用沖泡咖啡和沖泡茶的例子
加工流程:
咖啡沖泡法:1.把水煮沸、2.用沸水沖泡咖啡、3.把咖啡倒進杯子、4.加糖和牛奶
茶沖泡法: 1.把水煮沸、2.用沸水沖泡茶葉、3.把 茶 倒進杯子、4.加蜂蜜
實踐步驟:
1>創建一個模板(抽象)類:Beverage(飲料) 這里包含”骨架”
package com.kaishengit.beverage;public abstract class Beverage {/** * 沖泡咖啡或茶...流程 */public final void create(){boilWater();//把水煮沸brew();//用沸水沖泡...pourInCup();//把...倒進杯子addCoundiments();//加...}public abstract void addCoundiments();public abstract void brew();public void boilWater() {System.out.println("煮開水");}public void pourInCup() {System.out.println("倒進杯子");} }2>創建一個咖啡類(Coffee)和茶(Tea)類,都繼承Beverage抽象類
1.咖啡(Coffee)
package com.kaishengit.beverage;public class Coffee extends Beverage{@Overridepublic void addCoundiments() {System.out.println("添加糖和牛奶"); }@Overridepublic void brew() {System.out.println("用水沖咖啡");} }2. 茶(Tea)
package com.kaishengit.beverage;public class Tea extends Beverage{@Overridepublic void addCoundiments() {System.out.println("添加蜂蜜");}@Overridepublic void brew() {System.out.println("用水沖茶");}}
?
12. 觀察者模式
定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一主題對象
模式中的角色
抽象主題(Subject):它把所有觀察者對象的引用保存到一個聚集里,每個主題都可以有任何數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象。
具體主題(ConcreteSubject):將有關狀態存入具體觀察者對象;在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。
抽象觀察者(Observer):為所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
具體觀察者(ConcreteObserver):實現抽象觀察者角色所要求的更新接口,以便使本身的狀態與主題狀態協調
想想自己blog的氣象站的例子(headfirst 設計模式中的例子)
?
13. 迭代器模式
迭代器模式提供一種方法順序訪問一個聚合對象中各個元素
迭代器角色(Iterator):迭代器角色負責定義訪問和遍歷元素的接口
具體迭代器角色(Concrete Iterator):具體迭代器角色要實現迭代器接口,并要記錄遍歷中的當前位置。
Aggregate (聚合): 聚合定義創建相應迭代器對象的接口
ConcreteAggregate (具體聚合): 具體聚合實現創建相應迭代器的接口,該操作返回ConcreteIterator的一個適當的實例
比如: 早期電視機, 按電視上按鈕換臺那種, 當我們換頻道時, 重要的不是幾頻道, 而是節目內容.
在面向對象的軟件設計中, 我們經常會遇到一類集合對象, 這類集合對象的內部結構可能有著各種各樣的實現, 但是歸結起來, 無非有兩點是我們關心的: 一是集合內部的數據存儲結構, 二是遍歷這個集合內部的數據. Iterator 模式就是分離了集合對象的遍歷行為.
首先有一個抽象的聚集, 所謂聚集就是數據的集合, 可以循環去訪問它, 它只有一個方法 GetIterator()讓子類去實現, 用來獲得一個迭代器對象.
抽象迭代器: Iterator, 它用來訪問聚集的類, 封裝了一些方法, 通常會有 MoveNext(), CurrentItem(), First(), Next()
具體聚集 ConcreteList: 它實現了抽象聚集中的唯一方法, 同時再里面保存了一組數據
具體迭代器 ConcreteIterator: 具體迭代器, 它實現了迭代器中的4個方法, 在它的構造函數中需要接受一個具體聚集類型的參數.
?
14. 責任鏈模式
責任鏈模式使多個對象都有機會處理請求
抽象處理者 Handler: 定義出一個處理請求的接口,如果需要,接口可以定義出一個方法,以設定和返回對下家的引用。這個角色通常由一個抽象類或接口實現。
具體處理者(ConcreteHandler)角色:具體處理者接到請求后,可以選擇將請求處理掉,或者將請求傳給下家。由于具體處理者持有對下家的引用,因此,如果需要,具體處理者可以訪問下家。
比如: 請假,審批的例子, 在公司里,如果你的請假時間小于0.5天,那么只需要向項目經理打聲招呼就OK了, 如果超過了0.5天,但是還小于2天,那么就要去找人事部處理,當然,這就要扣工資了, 如果超過了2天,你就需要去找總經理了,工資當然也玩完了。那么,對于我們來說,這個流程就是這樣的。
?
也就是這樣一個過程,你需要和你的直接上級——項目經理去打交道,最終可能是項目經理給你回郵件,可能是人事部給你回郵件,也可能是總經理給你回郵件。內部的過程其實應該是個黑盒子,你并不知道內部的消息是如何處理的。你需要找到的,只是你想要第一個交付的對象而已.
下邊是一個審批例子的具體代碼.
抽象處理者角色
public abstract class Handler {/** * 持有下一個處理請求的對象 */protected Handler successor = null;/** * 取值方法 */public Handler getSuccessor() {return successor;}/** * 設置下一個處理請求的對象 */public void setSuccessor(Handler successor) {this.successor = successor;}/** * 處理聚餐費用的申請 * @param user 申請人 * @param fee 申請的錢數 * @return 成功或失敗的具體通知 */public abstract String handleFeeRequest(String user , double fee);具體處理者角色
項目經理
public class ProjectManager extends Handler {@Overridepublic String handleFeeRequest(String user, double fee) {String str = "";//項目經理權限比較小,只能在500以內if(fee < 500){//為了測試,簡單點,只同意張三的請求if("張三".equals(user)){str = "成功:項目經理同意【" + user + "】的聚餐費用,金額為" + fee + "元"; }else{//其他人一律不同意str = "失敗:項目經理不同意【" + user + "】的聚餐費用,金額為" + fee + "元";}}else{//超過500,繼續傳遞給級別更高的人處理if(getSuccessor() != null){return getSuccessor().handleFeeRequest(user, fee);}}return str;}}部門經理
public class DeptManager extends Handler {@Overridepublic String handleFeeRequest(String user, double fee) {String str = "";//部門經理的權限只能在1000以內if(fee < 1000){//為了測試,簡單點,只同意張三的請求if("張三".equals(user)){str = "成功:部門經理同意【" + user + "】的聚餐費用,金額為" + fee + "元"; }else{//其他人一律不同意str = "失敗:部門經理不同意【" + user + "】的聚餐費用,金額為" + fee + "元";}}else{//超過1000,繼續傳遞給級別更高的人處理if(getSuccessor() != null){return getSuccessor().handleFeeRequest(user, fee);}}return str;}}部長
public class GeneralManager extends Handler {@Overridepublic String handleFeeRequest(String user, double fee) {String str = "";//總經理的權限很大,只要請求到了這里,他都可以處理if(fee >= 1000){//為了測試,簡單點,只同意張三的請求if("張三".equals(user)){str = "成功:總經理同意【" + user + "】的聚餐費用,金額為" + fee + "元"; }else{//其他人一律不同意str = "失敗:總經理不同意【" + user + "】的聚餐費用,金額為" + fee + "元";}}else{//如果還有后繼的處理對象,繼續傳遞if(getSuccessor() != null){return getSuccessor().handleFeeRequest(user, fee);}}return str;}}客戶端類 (測試)
public class Client {public static void main(String[] args) {//先要組裝責任鏈Handler h1 = new GeneralManager();Handler h2 = new DeptManager();Handler h3 = new ProjectManager();h3.setSuccessor(h2);h2.setSuccessor(h1);//開始測試String test1 = h3.handleFeeRequest("張三", 300);System.out.println("test1 = " + test1);String test2 = h3.handleFeeRequest("李四", 300);System.out.println("test2 = " + test2);System.out.println("---------------------------------------");String test3 = h3.handleFeeRequest("張三", 700);System.out.println("test3 = " + test3);String test4 = h3.handleFeeRequest("李四", 700);System.out.println("test4 = " + test4);System.out.println("---------------------------------------");String test5 = h3.handleFeeRequest("張三", 1500);System.out.println("test5 = " + test5);String test6 = h3.handleFeeRequest("李四", 1500);System.out.println("test6 = " + test6);}}輸出結果:
?
15. 命令模式
將一個請求封裝成為一個對象, 使可以用不同的請求對客戶進行參數化
命令角色(Command):聲明執行操作的接口。有java接口或者抽象類來實現。
具體命令角色(Concrete Command):將一個接收者對象綁定于一個動作;調用接收者相應的操作,以實現命令角色聲明的執行操作的接口
客戶角色(Client):創建一個具體命令對象(并可以設定它的接收者
請求者角色(Invoker):調用命令對象執行這個請求
接收者角色(Receiver):知道如何實施與執行一個請求相關的操作。任何類都可能作為一個接收者
比如: 電視機遙控器
電視機是請求的接收者Receiver,遙控器是請求的發送者Invoker, 遙控器上有一些按鈕,不同的按鈕對應電視機的不同操作Command. 抽象命令角色由一個命令接口來扮演, 有三個具體的命令類實現了抽象命令接口,這三個具體命令類分別代表三種操作:打開電視機、關閉電視機和切換頻道
代碼如下: public interface Command {public void execute(); }public class ConcreteCommand implements Command {private Receiver receiver = null;private String state;public ConcreteCommand(Receiver receiver){this.receiver = receiver;} public void execute() {receiver.action();} }public class Receiver {public void action(){//真正執行命令操作的功能代碼} }public class Invoker {private Command command = null;public void setCommand(Command command) {this.command = command;}public void runCommand() {command.execute();} }public class Client {public void assemble(){//創建接收者Receiver receiver = new Receiver();//創建命令對象,設定它的接收者Command command = new ConcreteCommand(receiver);//創建Invoker,把命令對象設置進去Invoker invoker = new Invoker();invoker.setCommand(command);} } 模擬電視機換臺的代碼: 下面給個例子,是模擬對電視機的操作有開機、關機、換臺命令。代碼如下//命令接收者 public class Tv {public int currentChannel = 0;public void turnOn() {System.out.println("The televisino is on.");}public void turnOff() {System.out.println("The television is off.");}public void changeChannel(int channel) {this.currentChannel = channel;System.out.println("Now TV channel is " + channel);} }//執行命令的接口 public interface Command {void execute(); }//開機命令 public class CommandOn implements Command {private Tv myTv;public CommandOn(Tv tv) {myTv = tv;}public void execute() {myTv.turnOn();} }//關機命令 public class CommandOff implements Command {private Tv myTv;public CommandOff(Tv tv) {myTv = tv;}public void execute() {myTv.turnOff();} }//頻道切換命令 public class CommandChange implements Command {private Tv myTv;private int channel;public CommandChange(Tv tv, int channel) {myTv = tv;this.channel = channel;}public void execute() {myTv.changeChannel(channel);} }//可以看作是遙控器吧 public class Control {private Command onCommand, offCommand, changeChannel;public Control(Command on, Command off, Command channel) {onCommand = on;offCommand = off;changeChannel = channel;}public void turnOn() {onCommand.execute();}public void turnOff() {offCommand.execute();}public void changeChannel() {changeChannel.execute();} }//測試類 public class Client {public static void main(String[] args) {// 命令接收者Tv myTv = new Tv();// 開機命令CommandOn on = new CommandOn(myTv);// 關機命令CommandOff off = new CommandOff(myTv);// 頻道切換命令CommandChange channel = new CommandChange(myTv, 2);// 命令控制對象Control control = new Control(on, off, channel);// 開機control.turnOn();// 切換頻道control.changeChannel();// 關機control.turnOff();} }執行結果為: The televisino is on. Now TV channel is 2 The television is off.?
16. 狀態模式
狀態模式容許一個對象在其內部狀態改變時改變它的行為 上下文環境(Context):它定義了客戶程序需要的接口并維護一個具體狀態角色的實例,將與狀態相關的操作委托給當前的Concrete State對象來處理. 抽象狀態(State):定義一個接口以封裝使用上下文環境的的一個特定狀態相關的行為 具體狀態(Concrete State):實現抽象狀態定義的接口 舉例: 電燈有兩個狀態,開(亮)與關(不亮),下面就用狀態模式來實現對電燈的控制 /// <summary>/// 電燈類,對應模式中的Context類/// </summary>public class Light{private LightState state;public Light(LightState state){this.state = state;}/// <summary>/// 按下電燈開關/// </summary>public void PressSwich(){state.PressSwich(this);}public LightState State{get { return state; }set { state = value; }} }/// <summary>/// 抽象的電燈狀態類,相當于State類/// </summary>public abstract class LightState{public abstract void PressSwich(Light light);}/// <summary>/// 具體狀態類, 開/// </summary>public class On : LightState{/// <summary>/// 在開狀態下,按下開關則切換到關的狀態。/// </summary>/// <param name="light"></param>public override void PressSwich(Light light){Console.WriteLine("Turn off the light.");light.State = new Off();}}/// <summary>/// 具體狀態類,關/// </summary>public class Off: LightState{/// <summary>/// 在關狀態下,按下開關則打開電燈。/// </summary>/// <param name="light"></param>public override void PressSwich(Light light){Console.WriteLine("Turn on the light.");light.State = new On();}} 客戶端代碼 class Program{static void Main(string[] args){// 初始化電燈,原始狀態為關Light light = new Light(new Off());// 第一次按下開關,打開電燈light.PressSwich();// 第二次按下開關,關閉電燈light.PressSwich();Console.Read();}} from: https://www.cnblogs.com/moveofgod/p/4078730.html總結
- 上一篇: HTML 5 视频/音频参考手册
- 下一篇: 超详细:常用的设计模式汇总