舉例講解設(shè)計(jì)模式中的訪問(wèn)者模式在Java編程中的運(yùn)用
訪問(wèn)者(Visitor)模式:封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素的操作,它可以在不改變這個(gè)數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作。訪問(wèn)者模式的結(jié)構(gòu)圖如下:
通過(guò)上圖可以看到他有如下角色:
抽象訪問(wèn)者(Visitor)角色:定義接口,聲明一個(gè)或多個(gè)訪問(wèn)操作。
具體訪問(wèn)者(ConcreteVisitor)角色:實(shí)現(xiàn)抽象訪問(wèn)者所聲明的接口,也就是抽象訪問(wèn)者所聲明的各個(gè)訪問(wèn)操作。
抽象元素(Visitable)角色:聲明一個(gè)接受操作,接受一個(gè)訪問(wèn)者對(duì)象作為一個(gè)參數(shù)。
具體元素結(jié)點(diǎn)(ConcreteElement)角色:實(shí)現(xiàn)抽象結(jié)點(diǎn)所規(guī)定的接受操作。
數(shù)據(jù)結(jié)構(gòu)對(duì)象(ObjectStructure)角色:可以遍歷結(jié)構(gòu)中的所有元素,提供一個(gè)接口讓訪問(wèn)者對(duì)象都可以訪問(wèn)每一個(gè)元素。
模擬代碼如下:
interface Visitor { void visit(Gladiolus g); void visit(Chrysanthemum c); }
// concrete visitor 名稱訪問(wèn) class StringVisitor implements Visitor { String s; public String toString() { return s; } public void visit(Gladiolus g) { s = "Gladiolus"; } public void visit(Chrysanthemum c) { s = "Chrysanthemum"; } }
// concrete visitor 蜜蜂訪問(wèn) class BeeVisitor implements Visitor { public void visit(Gladiolus g) { System.out.println("蜜蜂 來(lái) 訪問(wèn) Gladiolus"); } public void visit(Chrysanthemum c) { System.out.println("蜜蜂 來(lái) 訪問(wèn) Chrysanthemum"); } }
interface Flower { void accept(Visitor v); }
/* * concrete element 菊花 */ class Chrysanthemum implements Flower { public void accept(Visitor v) { v.visit(this); } }
// concrete element 劍蘭 class Gladiolus implements Flower { public void accept(Visitor v) { v.visit(this); } }
//這是Flower一個(gè)對(duì)象生成器 class FlowerGenerator { private static Random rand = new Random(); public static Flower newFlower() { switch (rand.nextInt(2)) { default: case 0: return new Gladiolus(); case 1: return new Chrysanthemum(); } } }
public class Test { /* * 首先在客戶端先獲得一個(gè)具體的訪問(wèn)者角色 遍歷對(duì)象結(jié)構(gòu) 對(duì)每一個(gè)元素調(diào)用accept方法,將具體訪問(wèn)者角色傳入 這樣就完成了整個(gè)過(guò)程 */ public static void main(String args[]) { List<Flower> flowers = new ArrayList<Flower>(); for (int i = 0; i < 10; i++) flowers.add(FlowerGenerator.newFlower()); Visitor visitor = new StringVisitor(); Iterator<Flower> iterator = flowers.iterator(); while (iterator.hasNext()) { iterator.next().accept(visitor); System.out.println(visitor); } System.out.println("---------------"); /* * 一個(gè)新的訪問(wèn)行為 :BeeVisitor 蜜蜂訪問(wèn) */ Visitor visitor2 = new BeeVisitor(); for (Flower flower : flowers) { flower.accept(visitor2); } } }
結(jié)果:
Gladiolus Chrysanthemum Chrysanthemum Gladiolus Chrysanthemum Chrysanthemum Chrysanthemum Chrysanthemum Gladiolus Gladiolus --------------- 蜜蜂 來(lái) 訪問(wèn) Gladiolus 蜜蜂 來(lái) 訪問(wèn) Chrysanthemum 蜜蜂 來(lái) 訪問(wèn) Chrysanthemum 蜜蜂 來(lái) 訪問(wèn) Gladiolus 蜜蜂 來(lái) 訪問(wèn) Chrysanthemum 蜜蜂 來(lái) 訪問(wèn) Chrysanthemum 蜜蜂 來(lái) 訪問(wèn) Chrysanthemum 蜜蜂 來(lái) 訪問(wèn) Chrysanthemum 蜜蜂 來(lái) 訪問(wèn) Gladiolus 蜜蜂 來(lái) 訪問(wèn) Gladiolus
有以下情形可以考慮使用訪問(wèn)者模式:
1、一個(gè)對(duì)象結(jié)構(gòu)包含很多類對(duì)象,它們有不同的接口,而你想對(duì)這些對(duì)象實(shí)施一些依賴于其具體類的操作。
2、需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的對(duì)象進(jìn)行很多不同的并且不相關(guān)的操作,而你想避免讓這些操作“污染”這些對(duì)象的類。Visitor使得你可以將相關(guān)的操作集中起來(lái)定義在一個(gè)類中。
3、當(dāng)該對(duì)象結(jié)構(gòu)被很多應(yīng)用共享時(shí),用Visitor模式讓每個(gè)應(yīng)用僅包含需要用到的操作。
4、 定義對(duì)象結(jié)構(gòu)的類很少改變,但經(jīng)常需要在此結(jié)構(gòu)上定義新的操作。改變對(duì)象結(jié)構(gòu)類需要重定義對(duì)所有訪問(wèn)者的接口,這可能需要很大的代價(jià)。如果對(duì)象結(jié)構(gòu)類經(jīng)常改變,那么可能還是在這些類中定義這些操作較好。
這些個(gè)人看來(lái)都是建議,項(xiàng)目中還要具體問(wèn)題具體分析了。
相關(guān)文章
java設(shè)計(jì)模式之建造者模式學(xué)習(xí)
建造者模式(Builder Pattern)主要用于“分步驟構(gòu)建一個(gè)復(fù)雜的對(duì)象”,在這其中“分步驟”是一個(gè)穩(wěn)定的算法,下面給出了詳細(xì)的示例2014-01-01使用jvisualvm配合Visual GC插件監(jiān)控Java程序詳細(xì)總結(jié)
本節(jié)將會(huì)介紹一下jvisualvm的特性及作用、各個(gè)功能是如何使用的、最后會(huì)介紹jvisualvm的插件Visual GC的安裝及使用2021-09-09實(shí)戰(zhàn)分布式醫(yī)療掛號(hào)系統(tǒng)之設(shè)置微服務(wù)搭建醫(yī)院模塊
這篇文章主要為大家介紹了實(shí)戰(zhàn)分布式醫(yī)療掛號(hào)系統(tǒng)之搭建醫(yī)院設(shè)置微服務(wù)模塊,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04SpringMVC中利用@InitBinder來(lái)對(duì)頁(yè)面數(shù)據(jù)進(jìn)行解析綁定的方法
本篇文章主要介紹了SpringMVC中利用@InitBinder來(lái)對(duì)頁(yè)面數(shù)據(jù)進(jìn)行解析綁定的方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-03-03SpringBoot項(xiàng)目War包部署無(wú)法注冊(cè)到Nacos中的解決
這篇文章主要介紹了SpringBoot項(xiàng)目War包部署無(wú)法注冊(cè)到Nacos中的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01SpringCloud2020整合Nacos-Bootstrap配置不生效的解決
這篇文章主要介紹了SpringCloud2020整合Nacos-Bootstrap配置不生效的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01