本篇內(nèi)容介紹了“如何使用行為型模式”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:域名申請、虛擬空間、營銷軟件、網(wǎng)站建設(shè)、札達(dá)網(wǎng)站維護(hù)、網(wǎng)站推廣。
狀態(tài)模式的好處是將與特定狀態(tài)相關(guān)的行為局部化,并且將不同狀態(tài)的行為分割開來。
將特定相關(guān)的行為都放入一個對象中,由于所有與狀態(tài)相關(guān)的代碼都存在于某個ConcreteState
中,所以通過定義新的子類可以很容易地增加新的狀態(tài)和轉(zhuǎn)換。
Context:上下文,定義了客戶程序需要的接口并維護(hù)一個狀態(tài)類。
State:狀態(tài)類,定義一個接口以封裝上下文環(huán)境的一個特定狀態(tài)相關(guān)的行為,與狀態(tài)相關(guān)的操作委托給具體的state對象進(jìn)行處理。
Concrete State:具體狀態(tài)類
采用的例子是王者里面的,要么在打團(tuán)要么在打團(tuán)的路上,這就涉及到了狀態(tài)的轉(zhuǎn)換。
State
public interface State { void handle(Context context); }
Concrete State
回城狀態(tài)
public class ConcreteStateBack implements State{ @Override public void handle(Context context) { System.out.println("沒狀態(tài)了,回城補(bǔ)個狀態(tài)先"); context.setState(new ConcreteStateWalk()); } }
打團(tuán)狀態(tài)
public class ConcreteStateFight implements State{ @Override public void handle(Context context) { System.out.println("大招一按,蒼穹一開,雙手一放,要么黑屏,要么五殺"); context.setState(new ConcreteStateBack()); } }
打團(tuán)的路上狀態(tài)
public class ConcreteStateWalk implements State{ @Override public void handle(Context context) { System.out.println("狀態(tài)已滿,等我集合打團(tuán)"); context.setState(new ConcreteStateFight()); } }
失敗狀態(tài)
public class ConcreteStateDefeated implements State{ @Override public void handle(Context context) { System.out.println("Defeated!!!"); } }
Context
public class Context { private State state; public State getState() { return state; } public void setState(State state) { this.state = state; } public Context(State state) { this.state = state; } public void request() { state.handle(this); } }
Client
public class Client { public static void main(String[] args) { Context context = new Context(new ConcreteStateWalk()); for (int i = 0; i < 8; i++) { context.request(); } context.setState(new ConcreteStateDefeated()); context.request(); } }
策略模式是一種定義一系列算法的方法,但是這些方法最終完成的都是相同的工作,只是策略不同,也就是實(shí)現(xiàn)不同。
它可以以相同的方式來調(diào)用所有的算法,減少了各種算法類和使用算法類之間的耦合。
Context:上下文,內(nèi)部有個strategy屬性,并且能夠通過其調(diào)用策略
Strategy:策略接口或者抽象類,定義了策略的方法
Concrete Strategy:具體的策略
還是拿游戲舉例,最終的目的都是為了贏,但是具體的方式可能要根據(jù)對方的陣容做出改變。
Context
public class Context { Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void invokeStrategy() { strategy.play(); } }
Strategy
public interface Strategy { void play(); }
Concrete Strategy
public class ConcreteStrategyAttackMid implements Strategy{ @Override public void play() { System.out.println("集合進(jìn)攻中路"); } }
public class ConcreteStrategyGank implements Strategy{ @Override public void play() { System.out.println("轉(zhuǎn)線抓人推塔"); } }
public class ConcreteStrategyInvade implements Strategy{ @Override public void play() { System.out.println("入侵野區(qū)"); } }
Client
public class Client { public static void main(String[] args) { Context context = new Context(new ConcreteStrategyAttackMid()); context.invokeStrategy(); context = new Context(new ConcreteStrategyGank()); context.invokeStrategy(); context = new Context(new ConcreteStrategyInvade()); context.invokeStrategy(); } }
模板方法就是定義一個操作的算法的骨架,而將一些步驟延遲到子類種。模板方法使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義改算法的某些特定步驟。
簡而言之就是,我給你一個模板,步驟是哪些,但是具體怎么實(shí)現(xiàn)看個人。
Abstract Class:實(shí)現(xiàn)一個模板方法,定義了算法的估計
Concrete Class:對模板中各個算法的不同實(shí)現(xiàn)
都知道電腦的組裝都是有一個模板的,需要哪些零件都是固定的,不同的是零件的采用不同。這樣我們就可以把組裝作為一個行為模板給封裝起來。
Abstract Class
public abstract class AbstractClass { public void assemble() { System.out.println("開始模板組裝電腦"); cpu(); radiating(); screen(); } public abstract void cpu(); public abstract void radiating(); public abstract void screen(); }
Concrete Class
public class ConcreteClassMid extends AbstractClass{ @Override public void cpu() { System.out.println("Intel 10900K, Intel偶爾的神"); } @Override public void radiating() { System.out.println("雙銅散熱管"); } @Override public void screen() { System.out.println("75hz高素質(zhì)屏幕"); } }
public class ConcreteClassTop extends AbstractClass{ @Override public void cpu() { System.out.println("AMD5950X,AMD永遠(yuǎn)的神"); } @Override public void radiating() { System.out.println("雙銅散熱管加液冷散熱"); } @Override public void screen() { System.out.println("144hz電競屏"); } }
Client
public class Client { public static void main(String[] args) { AbstractClass templateToAssembleComputer = new ConcreteClassMid(); templateToAssembleComputer.assemble(); templateToAssembleComputer = new ConcreteClassTop(); templateToAssembleComputer.assemble(); } }
到這里有沒有印象之前說過的建造者模式,可以說非常相似,因為建造者模式就是借助了模板方法模式來實(shí)現(xiàn)的。
在不破壞封裝的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài),這樣可以在以后將對象恢復(fù)到原先保存的狀態(tài)。備忘錄嘛,也是比較形象的,就像我們解題的時候可以把過程寫下來看,最后可以按照步驟檢查,知道哪里出了問題,從那里恢復(fù)解題的過程,從而正確解題。
Originator:發(fā)起者是我們需要記住狀態(tài)的對象,以便在某個時刻恢復(fù)它。
Caretaker:管理者是負(fù)責(zé)觸發(fā)發(fā)起者的變化或者觸發(fā)發(fā)起者返回先前狀態(tài)動作的類。
Memento:備忘錄是負(fù)責(zé)存儲發(fā)起者內(nèi)部狀態(tài)的類。備忘錄提供了設(shè)置狀態(tài)和獲取狀態(tài)的方法,但是這些方法應(yīng)該對管理者隱藏。
**場景:**大家都玩過超級瑪麗,合金彈頭,或者i wanna這類的游戲叭。有什么組成呢,一個是玩家(Originator),一個是經(jīng)常需要存檔的檔案(Memento),還有一個是游戲后臺管理(Caretaker)。
對于玩家而言,可以存檔(setMemento和createMemento),也可以讀檔,恢復(fù)到上次存檔的位置(restoreMemento)。
Originator
(玩家)
public class OriginatorPlayer { private String name; private String status; public OriginatorPlayer(String name) { this.name = name; } //交給游戲后臺處理 1 public MementoGameState create() { return new MementoGameState(status); } //玩家存檔 2 public void save(String status) { this.status = status; System.out.println("存檔:" + status); } public void read(MementoGameState gameState) { this.status = gameState.getGameStatus(); System.out.println("讀檔:" + status); } }
其實(shí)我覺得1,2步是可以合起來寫成下面這樣子
public MementoGameState save(String status) { this.status = status; System.out.println("存檔:" + status); return new MementoGameState(status); }
Memento
(游戲狀態(tài))
public class MementoGameState { private String gameStatus = ""; public MementoGameState(String gameStatus) { this.gameStatus = gameStatus; } public String getGameStatus() { return gameStatus; } }
Caretaker
(后臺管理)
public class CaretakerGameManager { MementoGameState gameState; public MementoGameState getGameState() { return gameState; } //這是后臺真正存檔 public void setGameState(MementoGameState gameState) { System.out.println("系統(tǒng)已經(jīng)存檔: " + gameState.getGameStatus()); this.gameState = gameState; } }
Client
public class Client { public static void main(String[] args) { OriginatorPlayer cutey = new OriginatorPlayer("cutey"); CaretakerGameManager gameManager = new CaretakerGameManager(); //玩家自己點(diǎn)了存檔,但是不一定存成功 cutey.save("第一關(guān)"); //后臺要處理玩家的存檔的請求(imperfect.create()) gameManager.setGameState(cutey.create()); cutey.save("第二關(guān)"); gameManager.setGameState(cutey.create()); //這種情況就是可能我們點(diǎn)了存檔,還沒有成功就退出了 cutey.save("第三關(guān)"); //讀取檔案 cutey.read(gameManager.getGameState()); } }
仔細(xì)地看代碼會發(fā)現(xiàn),說到底講備忘錄,備忘的是不是就是游戲角色的狀態(tài),為此專門有一個類(GameState)來存這個狀態(tài)。
在恢復(fù)狀態(tài)的時候,在讀取備忘錄中的狀態(tài)賦給游戲角色中。所以歸根結(jié)底都是如何保存游戲角色的狀態(tài),然后在需要的時候可以恢復(fù)。
那是不是一定要新建一個類來幫我們保存呢,如果我們直接保存的是上個階段的游戲角色(而不是單純的游戲狀態(tài)),然后讀檔的時候直接讀上個階段的游戲角色可以嗎?
也就是發(fā)起人(Originator)也充當(dāng)了備忘錄(Memento)肯定是可以的。
又來想,要存的是自己,要拷貝的是自己來充當(dāng)備忘錄,為了節(jié)省空間,會用到之后講的原型模式。
到這里的話,普通的備忘錄模式就已經(jīng)講完了,下面要講的都是基于普通上進(jìn)行的改進(jìn),可看可不看。
玩家:
public class PlayerC implements Cloneable { private String name; private String state; public PlayerC(String name) { this.name = name; } public String getState() { return state; } public void setState(String state) { System.out.println("玩家進(jìn)行到:" + state); this.state = state; } //存檔,存的是自己 public PlayerC create() { System.out.println("玩家存檔:" + this.clone().getState()); return this.clone(); } //讀檔 public void play(PlayerC playerC) { System.out.println("玩家讀檔:" + playerC.getState()); setState(playerC.getState()); } //克隆自己 @Override public PlayerC clone() { try { return (PlayerC) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return null; } }
后臺管理:
public class GameManagerC { PlayerC playerC; public PlayerC getPlayerC() { return playerC; } //真正的存檔 public void setPlayerC(PlayerC playerC) { this.playerC = playerC; } }
Client:
public class ClientC { public static void main(String[] args) throws CloneNotSupportedException { PlayerC playerC = new PlayerC("perfext"); GameManagerC gameManagerC = new GameManagerC(); //分析和普通模式一樣,就不再贅述 playerC.setState("%10"); gameManagerC.setPlayerC(playerC.create()); playerC.setState("%20"); gameManagerC.setPlayerC(playerC.create()); playerC.setState("%30"); playerC.play(gameManagerC.getPlayerC()); } }
上面甚至還不是最簡潔的,因為其實(shí)我們存檔還是要在后臺管理類里面存,當(dāng)然這是希望看到的。想想后臺管理類的作用是干嘛的,是用來管理備忘錄的,既然備忘錄類都可以省略,后臺管理類自然也可以精簡掉。
也就是說,玩家的狀態(tài)保存在玩家的內(nèi)部,但是這與定義不符合,在一開始我特意加粗了”在該對象之外保存這個狀態(tài)“。所以說本篇博客就不再講述這種方式的實(shí)現(xiàn),也比較簡單(提示:在玩家類內(nèi)部聲明一個成員變量作為恢復(fù)的游戲角色)。
上面講的都是比較簡單的備忘錄模式,還有兩種比較常用的,一種是一個角色有多個狀態(tài)同時需要備忘,先講這種,另外一種賣個關(guān)子。
場景:一個角色有多個狀態(tài),那還是拿打游戲的例子,不過游戲角色不僅僅是第幾關(guān)。新的游戲角色有,打到了哪個階段,等級是多少以及裝備三個狀態(tài)。
玩家:
public class PlayerS { private String name; private String equipment; private String schedule; private String grade; //存檔 public GameStateS save() { System.out.println("玩家存檔:" + toString()); return new GameStateS(this); } //讀檔案,從保存的狀態(tài)中一個個讀出來 public void read(GameStateS gameStateS) { equipment = (String) gameStateS.getStates().get("equipment"); schedule = (String) gameStateS.getStates().get("schedule"); grade = (String) gameStateS.getStates().get("grade"); System.out.println("玩家讀檔:" + toString()); } public PlayerS(String name) { this.name = name; } /** * 省略 * 1.toString方法,用來方便打印 * 2.set方法,用來方便玩家存檔 * 3.get方法,方便存儲玩家的狀態(tài) */ }
游戲狀態(tài)(檔案):
public class GameStateS { //多狀態(tài),所以用hashmap來保存 private HashMap<String, Object> states = new HashMap<>(); //保存著玩家的狀態(tài) public GameStateS(PlayerS playerS) { states.put("schedule", playerS.getSchedule()); states.put("grade", playerS.getGrade()); states.put("equipment", playerS.getEquipment()); } public HashMap<String, Object> getStates() { return states; } }
后臺管理:
public class GameManagerS { private GameStateS gameStateS; public GameStateS getGameStateS() { return gameStateS; } //真正存檔 public void setGameStateS(GameStateS gameStateS) { System.out.println("系統(tǒng)已經(jīng)存檔!"); this.gameStateS = gameStateS; } }
Client:
public class ClientS { public static void main(String[] args) { PlayerS player = new PlayerS("perfext"); GameManagerS gameManagerS = new GameManagerS(); player.setSchedule("10%"); player.setEquipment("2件套"); player.setGrade("6級"); gameManagerS.setGameStateS(player.save()); player.setSchedule("30%"); player.setEquipment("4件套"); player.setGrade("10級"); gameManagerS.setGameStateS(player.save()); player.setSchedule("80%"); player.setEquipment("6件套"); player.setGrade("15級"); System.out.println("忘記存檔了!已經(jīng)打到了:"); System.out.println(player.toString()); player.read(gameManagerS.getGameStateS()); } }
本質(zhì)還是那樣,沒有太大變化,就是把狀態(tài)用hashmap做了一個封裝。
目前為止,對于上面所講的所有備忘錄模式,不知道各位小伙伴有沒有發(fā)現(xiàn)一個問題,就是在恢復(fù)的時候,只能恢復(fù)特定的狀態(tài)(一般是最后備忘的那個狀態(tài))。
但是在現(xiàn)實(shí)社會中,在碼字或者打代碼的時候總你能夠ctrl + z(撤銷)好幾次,可以撤銷回滿意的狀態(tài)。下面要講的應(yīng)該可以幫助到你。
原諒我不知道怎么高大上專業(yè)的表述這種備忘錄模式。
**場景:**再用游戲講的話不太清楚,接下來打字員(Originator)打字,內(nèi)容(Memento)交給電腦(Caretaker)保存來演示。
打字員:
public class Typist { private String name; private String word; //最新的狀態(tài) private List<String> content = new ArrayList<>(); //所有的狀態(tài) int len = 0; //狀態(tài)的位置,根據(jù)這個位置來讀取 public Typist(String name) { this.name = name; } public void setWord(String word) { this.word = word; } //保存 public TypeContent save() { content.add(word); System.out.println("打字員保存:" + word); len++; //長度+1 return new TypeContent(content); } //讀取 public void read(TypeContent typeContent) { content = typeContent.getTypeContent(); System.out.println("目前顯示:" + content.get(--len)); //讀完后長度-1 } }
內(nèi)容:
public class TypeContent { private List<String> typeContent = new ArrayList<>(); //保存用戶寫的字 public TypeContent(List<String> typeContent) { this.typeContent = typeContent; } public List<String> getTypeContent() { return typeContent; } }
電腦:
public class Computer { private TypeContent typeContent; public TypeContent getTypeContent() { return typeContent; } //真正保存用戶寫的字 public void setTypeContent(TypeContent typeContent) { this.typeContent = typeContent; } }
Client:
public class ClientM { public static void main(String[] args) { Typist perfext = new Typist("perfext"); Computer computer = new Computer(); perfext.setWord("abcd"); computer.setTypeContent(perfext.save()); perfext.setWord("efg"); computer.setTypeContent(perfext.save()); perfext.setWord("hijkl"); computer.setTypeContent(perfext.save()); perfext.setWord("mnopq"); computer.setTypeContent(perfext.save()); perfext.read(computer.getTypeContent()); //模擬ctrl+z System.out.println("撤銷:"); perfext.read(computer.getTypeContent()); System.out.println("撤銷:"); perfext.read(computer.getTypeContent()); System.out.println("撤銷:"); perfext.read(computer.getTypeContent()); } }
“如何使用行為型模式”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
網(wǎng)頁題目:如何使用行為型模式
分享網(wǎng)址:http://jinyejixie.com/article4/ppehoe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、品牌網(wǎng)站設(shè)計、網(wǎng)站建設(shè)、Google、手機(jī)網(wǎng)站建設(shè)、小程序開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)