您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“行為型模式有哪些內(nèi)容”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“行為型模式有哪些內(nèi)容”吧!
責(zé)任鏈模式可以拆分為責(zé)任和鏈,責(zé)任是指有責(zé)任去干嘛,鏈可以參考鏈表嘛,有下一級(jí)。
場(chǎng)景:現(xiàn)在你是某公司的員工,拿到了一個(gè)比較緊急的文件(文件的緊急性肯定不一樣嘛),需要更高一層的領(lǐng)導(dǎo)來(lái)處理下文件。
文件類:
public class File { private FileClass fileClass; //文件的重要等級(jí) private String content; //文件的內(nèi)容 //省略 } //枚舉類表示文件的重要等級(jí) enum FileClass { NORMAL, IMPORTANT, EMERGENCY }
員工接口:
public interface IStaff { //獲取員工的名字 public String getName(); //獲取要處理文件的等級(jí) public FileClass getFileClass(); //獲取員工的需求 public String getRequest(); }
員工:
public class Staff implements IStaff { private File file; private String name; //省略構(gòu)造函數(shù) @Override public String getName() { return name; } @Override public FileClass getFileClass() { return file.getFileClass(); } @Override public String getRequest() { return "這份文件【" + file.getContent() +"】需要處理下"; } }
領(lǐng)導(dǎo)接口:
public interface IHandler { //處理文件 public void handle(IStaff staff); }
組長(zhǎng):
public class Leader implements IHandler { @Override public void handle(IStaff staff) { System.out.println(staff.getName() + ": " + staff.getRequest()); System.out.println("組長(zhǎng):現(xiàn)在處理"); } }
總監(jiān):
public class Director implements IHandler{ @Override public void handle(IStaff staff) { System.out.println(staff.getName() + ": " + staff.getRequest()); System.out.println("總監(jiān):現(xiàn)在處理"); } }
主管:
public class Supervisor implements IHandler { @Override public void handle(IStaff staff) { System.out.println(staff.getName() + ": " + staff.getRequest()); System.out.println("主管:現(xiàn)在處理"); } }
Client:
public class Client { public static void main(String[] args) { File file = new File(FileClass.IMPORTANT, "策劃方案"); IStaff staff = new Staff(file, "imperfect"); if(file.getFileClass().equals(FileClass.NORMAL)) { new Leader().handle(staff); } else if(file.getFileClass().equals(FileClass.IMPORTANT)) { new Director().handle(staff); } else if(file.getFileClass().equals(FileClass.EMERGENCY)) { new Supervisor().handle(staff); } else { System.out.println("權(quán)限不夠"); } } }
你瞅瞅,仔細(xì)品,這一堆if else直接在Client類給暴露出來(lái)了,而且是在Client中才進(jìn)行判斷不同等級(jí)給不同的領(lǐng)導(dǎo)處理。
通俗地比喻呢,就是員工拿到了文件后,把自己的組長(zhǎng),總監(jiān),主管全都叫到自己跟前,然后說(shuō),這份文件是比較重要的,給你們誰(shuí)處理才有權(quán)限。確實(shí)是可以完成人物,但是這樣的方式現(xiàn)實(shí)嗎?
接近現(xiàn)實(shí)的一種方式是怎么樣的呢,員工拿到文件后,首先給自己的直接領(lǐng)導(dǎo)組長(zhǎng),在領(lǐng)導(dǎo)層(handler)中的最低的一層(鏈頭)。接著組長(zhǎng)再看自己有沒(méi)有責(zé)任去處理文件,沒(méi)有的話再給下一層來(lái)處理,這就是責(zé)任鏈模式。
文件類和員工類不變,主要是領(lǐng)導(dǎo)層(handler)的變化。
抽象領(lǐng)導(dǎo)類:
public abstract class AbstractHandler { private FileClass fileClass; private AbstractHandler nextHandler; private String name; //在類構(gòu)造的時(shí)候就明確了職責(zé) //就像你入職就知道自己的責(zé)任是處理什么文件 public AbstractHandler(FileClass fileClass, String name) { this.fileClass = fileClass; this.name = name; } //取得領(lǐng)導(dǎo)的名字 public String getName() { return name; } //沒(méi)有責(zé)任,交給下一級(jí) public void setNextHandler(AbstractHandler nextHandler) { this.nextHandler = nextHandler; } //處理回應(yīng),每個(gè)人的回應(yīng)方式不一樣,所以抽象出來(lái) public abstract void respond(IStaff staff); //處理信息 public void handle(IStaff staff) { if(fileClass.equals(staff.getFileClass())) { respond(staff); } else { if(nextHandler != null) { nextHandler.respond(staff); } else { System.out.println("已經(jīng)到最高權(quán)限?。?!"); } } } }
組長(zhǎng):
public class Leader extends AbstractHandler { public Leader(String name) { super(FileClass.NORMAL, name); } @Override public void respond(IStaff staff) { System.out.println(staff.getName() + ": " + staff.getRequest()); System.out.println(getName() + "組長(zhǎng):做出了回應(yīng)"); } }
總監(jiān):
public class Director extends AbstractHandler{ public Director(String name) { super(FileClass.IMPORTANT, name); } @Override public void respond(IStaff staff) { System.out.println(staff.getName() + ": " + staff.getRequest()); System.out.println(getName() + "總監(jiān):做出了回應(yīng)"); } }
主管:
public class Supervisor extends AbstractHandler { public Supervisor(String name) { super(FileClass.EMERGENCY, name); } @Override public void respond(IStaff staff) { System.out.println(staff.getName() + ": " + staff.getRequest()); System.out.println(getName() + "主管:做出了回應(yīng)"); } }
Client:
public class Client { public static void main(String[] args) { File file = new File(FileClass.IMPORTANT, "營(yíng)銷方案"); IStaff staff = new Staff(file, "imperfect"); //創(chuàng)建領(lǐng)導(dǎo)層 AbstractHandler leader = new Leader("leaderWu"); AbstractHandler director = new Director("directorWu"); AbstractHandler supervisor = new Supervisor("supervisorWu"); //設(shè)置層級(jí)關(guān)系,跟鏈表類似 leader.setNextHandler(director); director.setNextHandler(supervisor); //首先交給直接領(lǐng)導(dǎo)處理 leader.handle(staff); } }
**優(yōu)點(diǎn):**處理和請(qǐng)求分開(kāi),員工不知道最終文件是誰(shuí)處理的
**缺點(diǎn):**缺點(diǎn)也十分明顯,如果責(zé)任鏈很長(zhǎng),而處理者剛好在最后,是不是要遍歷完責(zé)任鏈。這樣性能就比較低,在實(shí)際使用中,一般會(huì)折這一個(gè)最大鏈長(zhǎng)來(lái)保證性能。
命令模式,一句話就是給你一個(gè)命令,必須要遵守并且執(zhí)行,有點(diǎn)像是軍隊(duì)里面“服從命令是軍人的天職”。
不知道大學(xué)有沒(méi)有參加過(guò)數(shù)學(xué)建模,反正我是沒(méi)有參加過(guò),但是有了解過(guò)一般構(gòu)成,一個(gè)小隊(duì)里面一般有主要負(fù)責(zé)搜索的同學(xué),寫代碼的同學(xué),寫論文的同學(xué)和指導(dǎo)老師
抽象成員類(receiver):
public abstract class NTeammate { public abstract void changeRequire(); public abstract void modify(); public abstract void work(); }
Searcher:
public class NSearcher extends NTeammate { @Override public void changeRequire() { System.out.println("searcher 了解到需求改變"); } @Override public void modify() { } @Override public void work() { System.out.println("searcher 開(kāi)始搜索相關(guān)信息"); } }
Writer:
public class NWriter extends NTeammate { @Override public void changeRequire() { System.out.println("writer 了解到需求改變"); } @Override public void modify() { System.out.println("writer 修改論文"); } @Override public void work() { System.out.println("writer 開(kāi)始寫論文"); } }
Coder:
public class NCoder extends NTeammate { @Override public void changeRequire() { System.out.println("coder 了解到需求改變"); } @Override public void modify() { System.out.println("coder 修改代碼"); } @Override public void work() { System.out.println("coder 開(kāi)始碼代碼"); } }
Teacher:
public class NTeacher { public static void main(String[] args) { NTeammate writer = new NWriter(); //需要改文章了 writer.modify(); writer.work(); } }
一開(kāi)始,老師看到寫的文展不夠簡(jiǎn)潔,所以就打電話給writer,讓他修改,所以就有了上面的Teacher類。這樣其實(shí)還好,因?yàn)槲恼侣?,修改?rùn)色就好了。
過(guò)了一天,老師仔細(xì)看了下后,發(fā)現(xiàn)代碼的算法有bug,這個(gè)漏洞導(dǎo)致了不僅coder要修改代碼,writer也要修改相應(yīng)地方的文章。
老師這下不僅要聯(lián)系writer,也得聯(lián)系coder,那么Teacher類應(yīng)該怎么修改呢?
public class NTeacher { public static void main(String[] args) { NTeammate writer = new NWriter(); NTeammate coder = new NCoder(); //需要改bug和文章了 writer.modify(); writer.work(); coder.modify(); coder.work(); } }
可以發(fā)現(xiàn),就多了一個(gè)需求,代碼較之前已經(jīng)有很大的改動(dòng)了,這是我們不希望看到的??赡苡械男』锇闀?huì)想到利用中介者模式,不過(guò)中介者模式是為了減小類和類之間的耦合,這個(gè)例子中的searcher,writer,coder并沒(méi)有耦合,都在各司其職。
如果小隊(duì)里面有個(gè)隊(duì)長(zhǎng)(Invoker)就好了,可以和老師(client)溝通,不止這樣,老師的指令實(shí)現(xiàn)起來(lái)肯定是String類型,我們可以把指令封裝稱一個(gè)類(command),隊(duì)長(zhǎng)只需要發(fā)布命令,命令指示隊(duì)員(receiver)來(lái)做什么。這就是命令模式,隊(duì)員必須執(zhí)行命令要求做的。
抽象隊(duì)員以及具體隊(duì)員還是和上面一樣,這里就不再贅述。
抽象命令類:
public abstract class AbstractCommand { protected Coder coder = new Coder(); protected Searcher searcher = new Searcher(); protected Writer writer = new Writer(); //一定要有個(gè)執(zhí)行的方法,下達(dá)一個(gè)命令 public abstract void execute(); }
具體命令類(Command):
有哪些命令,都可以封裝起來(lái)
改變需求:
public class ChangeInfoCommand extends AbstractCommand { @Override public void execute() { searcher.changeRequire(); writer.changeRequire(); coder.changeRequire(); } }
修改文章:
public class ModifyArticleCommand extends AbstractCommand { @Override public void execute() { writer.modify(); writer.work(); } }
修改代碼:
public class ModifyCodeCommand extends AbstractCommand { @Override public void execute() { coder.modify(); coder.work(); writer.modify(); writer.work(); } }
隊(duì)長(zhǎng)類(Invoke):
public class Captain { //和命令產(chǎn)生聯(lián)系 AbstractCommand abstractCommand; public Captain(AbstractCommand abstractCommand) { this.abstractCommand = abstractCommand; } public void invoke() { //發(fā)布命令要求隊(duì)員進(jìn)行相應(yīng)的動(dòng)作 abstractCommand.execute(); } }
老師類(Client):
public class Teacher { public static void main(String[] args) { AbstractCommand command = new ModifyCodeCommand(); Captain captain = new Captain(command); captain.invoke(); } }
如果老師覺(jué)得又不好了,這些怎么辦呢,沒(méi)有必要和成員練習(xí),只需要提出另外一個(gè)建議,隊(duì)長(zhǎng)也不要跟隊(duì)員練習(xí),只需要發(fā)布命令,由命令指示隊(duì)員去做。修改就是這么簡(jiǎn)單,一行代碼的事情。
public class Teacher { public static void main(String[] args) { //AbstractCommand command = new ModifyCodeCommand(); AbstractCommand command = new ModifyArticleCommand(); Captain captain = new Captain(command); captain.invoke(); } }
如果說(shuō),誒,改代碼的時(shí)候不僅需要修改bug和修正文章,也需要searcher來(lái)搜集信息,怎么辦呢?
public class ModifyCodeCommand extends AbstractCommand { @Override public void execute() { searcher.work(); //只需要在具體的命令里面添加即可,客戶端是完全不知道的 coder.modify(); coder.work(); writer.modify(); writer.work(); } }
還有一種情況就是,某些修改之后,老師發(fā)現(xiàn)還是之前的版本比較好,這就要求每個(gè)隊(duì)員都有一個(gè)回調(diào)函數(shù)來(lái)撤銷動(dòng)作,返回到上一個(gè)狀態(tài),就是找到保存的之前版本的文件。只需要在抽象receiver類加一個(gè)回調(diào)函數(shù)即可:
public abstract class NTeammate { public abstract void changeRequire(); public abstract void modify(); public abstract void work(); //具體隊(duì)友在根據(jù)自己的方式實(shí)現(xiàn)回調(diào)方法 public abstract void rollback(); }
接著就是添加一個(gè)撤回命令
public class callBackCommand extends AbstractCommand { @Override public void execute() { //當(dāng)然,需要誰(shuí)撤回是可以改變的 searcher.rollback(); writer.rollback(); coder.rollback(); } }
這個(gè)無(wú)論是工作上還是學(xué)習(xí)中都是比較冷門的設(shè)計(jì)模式。解釋器模式由以下類組成
Context: Context用于封裝解釋器的全局信息,所有具體的解釋器均需要訪問(wèn)Context。
AbstractExpression: 一個(gè)抽象類或接口,聲明執(zhí)行的解釋方法,由所有具體的解釋器實(shí)現(xiàn)
TerminalExpression: 一種解釋器類,實(shí)現(xiàn)與語(yǔ)法的終結(jié)符相關(guān)的操作。終結(jié)符表達(dá)式必須終結(jié)被實(shí)現(xiàn)和實(shí)例化,因?yàn)樗硎颈磉_(dá)式的結(jié)尾。
NonTerminalExpreesion: 這是實(shí)現(xiàn)語(yǔ)法的不同規(guī)則或符號(hào)的類。對(duì)于每一種語(yǔ)法都應(yīng)該創(chuàng)建一個(gè)類。
這個(gè)東西解釋起來(lái)比較拗口,一時(shí)也沒(méi)有很好的通俗的解釋,那就直接看例子叭。
public interface Expression { public float interpret(); }
public class Number implements Expression{ private final float number; public Number(float number) { this.number = number; } @Override public float interpret() { return number; } }
還記得之前說(shuō)過(guò)的流嗎,TerminalExpression
就類似終結(jié)操作,而NonTerminalExpression
就是類似中間操作
public class Plus implements Expression{ Expression left; Expression right; public Plus(Expression left, Expression right) { this.left = left; this.right = right; } @Override public float interpret() { return left.interpret() + right.interpret(); } }
注意對(duì)于每一個(gè)語(yǔ)法都要有一個(gè)獨(dú)立的類
public class Minus implements Expression { Expression left; Expression right; public Minus(Expression left, Expression right) { this.left = left; this.right = right; } @Override public float interpret() { return left.interpret() - right.interpret(); } }
public class Evaluator { public static void main(String[] args) { Evaluator evaluator = new Evaluator(); System.out.println(evaluator.evaluate("3 4 +")); System.out.println(evaluator.evaluate("4 3 -")); System.out.println(evaluator.evaluate("4 3 - 2 +")); } public float evaluate(String expression) { Stack<Expression> stack = new Stack<>(); float result = 0; for (String token : expression.split(" ")) { Expression exp = null; if (isOperator(token)) { if (token.equals("+")) { exp = stack.push(new Plus(stack.pop(), stack.pop())); } else if (token.equals("-")) { exp = stack.push(new Minus(stack.pop(), stack.pop())); } if (null != exp) { result = exp.interpret(); stack.push(new Number(result)); } } if (isNumber(token)) { stack.push(new Number(Float.parseFloat(token))); } } return result; } private boolean isNumber(String token) { try { Float.parseFloat(token); return true; } catch (NumberFormatException e) { return false; } } private boolean isOperator(String token) { return token.equals("+") || token.equals("-"); } }
到此,相信大家對(duì)“行為型模式有哪些內(nèi)容”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。