Java設(shè)計(jì)模式之訪問(wèn)模式(Visitor者模式)介紹
Visitor定義:作用于某個(gè)對(duì)象群中各個(gè)對(duì)象的操作。它可以使你在不改變這些對(duì)象本身的情況下,定義作用于這些對(duì)象的新操作。
在Java中,Visitor模式實(shí)際上是分離了collection結(jié)構(gòu)中的元素和對(duì)這些元素進(jìn)行操作的行為。
為何使用Visitor模式
Java的Collection(包括Vector和Hashtable)是我們最經(jīng)常使用的技術(shù),可是Collection好象是個(gè)黑色大染缸,本來(lái)有各種鮮明類型特征的對(duì)象一旦放入后,再取出時(shí),這些類型就消失了。那么我們勢(shì)必要用If來(lái)判斷,如:
Iterator iterator = collection.iterator()
while (iterator.hasNext()) {
Object o = iterator.next();
if (o instanceof Collection)
messyPrintCollection((Collection)o);
else if (o instanceof String)
System.out.println("'"+o.toString()+"'");
else if (o instanceof Float)
System.out.println(o.toString()+"f");
else
System.out.println(o.toString());
}
在上例中,我們使用了 instanceof來(lái)判斷 o的類型。
很顯然,這樣做的缺點(diǎn)代碼If else if 很繁瑣,我們就可以使用Visitor模式解決它。
如何使用Visitor模式
針對(duì)上例,我們?cè)O(shè)計(jì)一個(gè)接口visitor訪問(wèn)者:
public interface Visitor
{
public void visitCollection(Collection collection);
public void visitString(String string);
public void visitFloat(Float float);
}
在這個(gè)接口中,將我們認(rèn)為Collection有可能的類的類型放入其中。
有了訪問(wèn)者,我們需要被訪問(wèn)者,被訪問(wèn)者就是我們Collection的每個(gè)元素Element,我們要為這些Element定義一個(gè)可以接受訪問(wèn)的接口(訪問(wèn)和被訪問(wèn)是互動(dòng)的,只有訪問(wèn)者,被訪問(wèn)者如果表示不歡迎,訪問(wèn)者就不能訪問(wèn))。
我們定義這個(gè)接口叫Visitable,用來(lái)定義一個(gè)Accept操作,也就是說(shuō)讓Collection每個(gè)元素具備可訪問(wèn)性。
public interface Visitable{
public void accept(Visitor visitor);
}
好了,有了兩個(gè)接口,我們就要定義他們的具體實(shí)現(xiàn)(Concrete class):
public class ConcreteElement implements Visitable
{
private String value;
public ConcreteElement(String string) {
value = string;
}
//定義accept的具體內(nèi)容 這里是很簡(jiǎn)單的一句調(diào)用
public void accept(Visitor visitor) {
visitor.visitString(this);
}
}
再看看訪問(wèn)者的Concrete實(shí)現(xiàn):
public class ConcreteVisitor implements Visitor
{
//在本方法中,我們實(shí)現(xiàn)了對(duì)Collection的元素的成功訪問(wèn)
public void visitCollection(Collection collection) {
Iterator iterator = collection.iterator()
while (iterator.hasNext()) {
Object o = iterator.next();
if (o instanceof Visitable)
((Visitable)o).accept(this);
}
public void visitString(String string) {
System.out.println("'"+string+"'");
}
public void visitFloat(Float float) {
System.out.println(float.toString()+"f");
}
}
在上面的visitCollection我們實(shí)現(xiàn)了對(duì)Collection每個(gè)元素訪問(wèn),只使用了一個(gè)判斷語(yǔ)句,只要判斷其是否可以訪問(wèn)。
至此,我們完成了Visitor模式基本架構(gòu)。
使用Visitor模式的前提
對(duì)象群結(jié)構(gòu)中(Collection) 中的對(duì)象類型很少改變,也就是說(shuō)訪問(wèn)者的身份類型很少改變,如上面中Visitor中的類型很少改變,如果需要增加新的操作,比如上例中我們?cè)贑oncreteElement具體實(shí)現(xiàn)外,還需要新的ConcreteElement2 ConcreteElement3。
可見(jiàn)使用Visitor模式是有前提的,在兩個(gè)接口Visitor和Visitable中,確保Visitor很少變化,變化的是Visitable,這樣使用Visitor最方便。
如果Visitor也經(jīng)常變化,也就是說(shuō),對(duì)象群中的對(duì)象類型經(jīng)常改變,一般建議是,不如在這些對(duì)象類中逐個(gè)定義操作,但是Java的Reflect技術(shù)解決了這個(gè)問(wèn)題。
相關(guān)文章
Java實(shí)現(xiàn)文件名倒序排序的技術(shù)指南
在實(shí)際開發(fā)過(guò)程中,我們經(jīng)常需要對(duì)文件進(jìn)行操作和處理,一個(gè)常見(jiàn)的需求是按文件名倒序排列文件列表,以便于文件的管理和查找,本文將介紹如何在Java中實(shí)現(xiàn)文件名倒序排序,并提供詳細(xì)的代碼案例,需要的朋友可以參考下2024-08-08
詳解全局事務(wù)注解@GlobalTransactional的識(shí)別
這篇文章主要為大家介紹了詳解全局事務(wù)注解@GlobalTransactional的識(shí)別源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Springboot中項(xiàng)目的屬性配置的詳細(xì)介紹
很多時(shí)候需要用到一些配置的信息,這些信息可能在測(cè)試環(huán)境和生產(chǎn)環(huán)境下會(huì)有不同的配置,本文主要介紹了Springboot中項(xiàng)目的屬性配置的詳細(xì)介紹,感興趣的可以了解一下2022-01-01
理解Java注解及Spring的@Autowired是如何實(shí)現(xiàn)的
今天通過(guò)本文帶領(lǐng)大家學(xué)習(xí)注解的基礎(chǔ)知識(shí),學(xué)習(xí)Spring的@Autowired是怎么實(shí)現(xiàn)的,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-07-07
基于java變量和作用域以及成員變量的默認(rèn)初始化(詳解)
下面小編就為大家介紹一下java變量和作用域以及成員變量的默認(rèn)初始化,具有很好的參考價(jià)值,希望對(duì)大家有所幫助2017-11-11
Springboot Mybatis-Plus數(shù)據(jù)庫(kù)單元測(cè)試實(shí)戰(zhàn)(三種方式)
這篇文章主要介紹了Springboot Mybatis-Plus數(shù)據(jù)庫(kù)單元測(cè)試實(shí)戰(zhàn)(三種方式),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12

