1 測(cè)評(píng)系統(tǒng)的需求完成測(cè)評(píng)系統(tǒng)需求 1) 將觀(guān)眾分為男人和女人,對(duì)歌手進(jìn)行測(cè)評(píng),當(dāng)看完某個(gè)歌手表演后,得到他們對(duì)該歌手不同的評(píng)價(jià)(評(píng)價(jià) 有不同的種類(lèi),比如 成功、失敗 等)
2) 傳統(tǒng)方案 2 傳統(tǒng)方式的問(wèn)題分析1) 如果系統(tǒng)比較小,還是 ok 的,但是考慮系統(tǒng)增加越來(lái)越多新的功能時(shí),對(duì)代碼改動(dòng)較大,違反了 ocp 原則, 不利于維護(hù) 2) 擴(kuò)展性不好,比如 增加了 新的人員類(lèi)型,或者管理方法,都不好做 3) 引出我們會(huì)使用新的設(shè)計(jì)模式 – 訪(fǎng)問(wèn)者模式 3 訪(fǎng)問(wèn)者模式基本介紹1) 訪(fǎng)問(wèn)者模式(Visitor Pattern),封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)的各元素的操作,它可以在不改變數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作。 2) 主要將數(shù)據(jù)結(jié)構(gòu)與數(shù)據(jù)操作分離,解決 數(shù)據(jù)結(jié)構(gòu)和操作耦合性問(wèn)題 3) 訪(fǎng)問(wèn)者模式的基本工作原理是:在被訪(fǎng)問(wèn)的類(lèi)里面加一個(gè)對(duì)外提供接待訪(fǎng)問(wèn)者的接口 4) 訪(fǎng)問(wèn)者模式主要應(yīng)用場(chǎng)景是:需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的對(duì)象進(jìn)行很多不同操作(這些操作彼此沒(méi)有關(guān)聯(lián)),同時(shí) 需要避免讓這些操作"污染"這些對(duì)象的類(lèi),可以選用訪(fǎng)問(wèn)者模式解決 4 訪(fǎng)問(wèn)者模式的原理類(lèi)圖
即(訪(fǎng)問(wèn)者模式的角色及職責(zé)) 1) Visitor 是抽象訪(fǎng)問(wèn)者,為該對(duì)象結(jié)構(gòu)中的 ConcreteElement 的每一個(gè)類(lèi)聲明一個(gè) visit 操作 2) ConcreteVisitor :是一個(gè)具體的訪(fǎng)問(wèn)值 實(shí)現(xiàn)每個(gè)有 Visitor 聲明的操作,是每個(gè)操作實(shí)現(xiàn)的部分. 3) ObjectStructure 能枚舉它的元素, 可以提供一個(gè)高層的接口,用來(lái)允許訪(fǎng)問(wèn)者訪(fǎng)問(wèn)元素 4) Element 定義一個(gè) accept 方法,接收一個(gè)訪(fǎng)問(wèn)者對(duì)象 5) ConcreteElement 為具體元素,實(shí)現(xiàn)了 accept 方法 5 訪(fǎng)問(wèn)者模式應(yīng)用實(shí)例應(yīng)用實(shí)例要求 1) 將人分為男人和女人,對(duì)歌手進(jìn)行測(cè)評(píng),當(dāng)看完某個(gè)歌手表演后,得到他們對(duì)該歌手不同的評(píng)價(jià)(評(píng)價(jià) 有不同的種類(lèi),比如 成功、失敗 等),請(qǐng)使用訪(fǎng)問(wèn)者模式來(lái)說(shuō)實(shí)現(xiàn) 2) 思路分析和圖解(類(lèi)圖)
3) 代碼實(shí)現(xiàn) package com.lin.Visitor; public abstract class Person { // 提供一個(gè)方法讓訪(fǎng)問(wèn)者可以訪(fǎng)問(wèn) public abstract void accept(Action action); } package com.lin.Visitor; //1. 這里我們使用到了雙分派, 即首先在客戶(hù)端程序中,將具體狀態(tài)作為參數(shù)傳遞 Woman 中(第一次分派) //2. 然后 Woman 類(lèi)調(diào)用作為參數(shù)的 "具體方法" 中方法 getWomanResult, 同時(shí)將自己(this)作為參數(shù) // 傳入,完成第二次的分派 public class Women extends Person{ @Override public void accept(Action action) { action.getWomenResult(this); } } package com.lin.Visitor; public class Man extends Person{ @Override public void accept(Action action) { action.getManResult(this); } } package com.lin.Visitor; public abstract class Action { // 得到男性的測(cè)評(píng) public abstract void getManResult(Person person); // 得到女性的測(cè)評(píng) public abstract void getWomenResult(Person person); } package com.lin.Visitor; public class Success extends Action { @Override public void getManResult(Person person) { System.out.println("男性觀(guān)眾給的評(píng)價(jià)是成功!"); } @Override public void getWomenResult(Person person) { System.out.println("女性觀(guān)眾給的評(píng)價(jià)是成功!"); } } package com.lin.Visitor; public class Fail extends Action { @Override public void getManResult(Person person) { System.out.println("男性觀(guān)眾給的評(píng)價(jià)是失??!"); } @Override public void getWomenResult(Person person) { System.out.println("女性觀(guān)眾給的評(píng)價(jià)是失??!"); } } package com.lin.Visitor; import java.util.LinkedList; import java.util.List; public class ObjectStructure { private List<Person> persons = new LinkedList<>(); // 添加 public void attach(Person person) { persons.add(person); } // 移除 public void detach(Person person) { persons.remove(person); } // 顯示 public void display(Action action) { for (Person person : persons) { person.accept(action); } } } package com.lin.Visitor; public class Client { public static void main(String[] args) { ObjectStructure objectStructure = new ObjectStructure(); objectStructure.attach(new Women()); objectStructure.attach(new Man()); objectStructure.attach(new Women()); objectStructure.attach(new Man()); Success success = new Success(); objectStructure.display(success); System.out.println("=========================="); Wait wait = new Wait(); objectStructure.display(wait); } }
4) 應(yīng)用案例的小結(jié)-雙分派 -上面提到了雙分派,所謂雙分派是指不管類(lèi)怎么變化,我們都能找到期望的方法運(yùn)行。雙分派意味著得到執(zhí)行的操作取決于請(qǐng)求的種類(lèi)和兩個(gè)接收者的類(lèi)型 - 以上述實(shí)例為例,假設(shè)我們要添加一個(gè) Wait 的狀態(tài)類(lèi),考察 Man 類(lèi)和 Woman 類(lèi)的反應(yīng),由于使用了雙分派,只需增加一個(gè) Action 子類(lèi)即可在客戶(hù)端調(diào)用即可,不需要改動(dòng)任何其他類(lèi)的代碼。 6 訪(fǎng)問(wèn)者模式的注意事項(xiàng)和細(xì)節(jié)
1) 訪(fǎng)問(wèn)者模式符合單一職責(zé)原則、讓程序具有優(yōu)秀的擴(kuò)展性、靈活性非常高 2) 訪(fǎng)問(wèn)者模式可以對(duì)功能進(jìn)行統(tǒng)一,可以做報(bào)表、UI、攔截器與過(guò)濾器,適用于數(shù)據(jù)結(jié)構(gòu)相對(duì)穩(wěn)定的系統(tǒng)
1) 具體元素對(duì)訪(fǎng)問(wèn)者公布細(xì)節(jié),也就是說(shuō)訪(fǎng)問(wèn)者關(guān)注了其他類(lèi)的內(nèi)部細(xì)節(jié),這是迪米特法則所不建議的, 這樣造成了具體元素變更比較困難 2) 違背了依賴(lài)倒轉(zhuǎn)原則。訪(fǎng)問(wèn)者依賴(lài)的是具體元素,而不是抽象元素 3) 因此,如果一個(gè)系統(tǒng)有比較穩(wěn)定的數(shù)據(jù)結(jié)構(gòu),又有經(jīng)常變化的功能需求,那么訪(fǎng)問(wèn)者模式就是比較合適的.
僅供參考,有錯(cuò)誤還請(qǐng)指出! 有什么想法,評(píng)論區(qū)留言,互相指教指教。 |
|
|
來(lái)自: 路人甲Java > 《待分類(lèi)》