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