訪問者模式
- 定義:封裝作用于某數(shù)據(jù)結(jié)構(gòu)(如List/Set/Map等)中的各元素操作
- 補充定義:可以在不改變各元素類的前提下,定義作用于這些元素的操作
- 類型:行為型
- 適用場景:
- 一個數(shù)據(jù)結(jié)構(gòu)(如List/Set/Map等)包含很多類型對象
- 數(shù)據(jù)結(jié)構(gòu)與數(shù)據(jù)操作分離
- 優(yōu)點:增加新的操作很容易,即增加一個新的訪問者
- 缺點:
- 增加新的數(shù)據(jù)結(jié)構(gòu)很困難
- 具體元素變更比較麻煩
- 相關設計模式:
- 訪問者模式和迭代器模式:都是在某種數(shù)據(jù)結(jié)構(gòu)上處理,訪問者模式主要用于對保存在數(shù)據(jù)結(jié)構(gòu)中的元素進行某種特定的處理,迭代器模式主要用于逐個遍歷保存在數(shù)據(jù)結(jié)構(gòu)中的元素,重點在于遍歷。
Coding
public abstract class Course { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public abstract void accept(IVisitor visitor); } public class FreeCourse extends Course { @Override public void accept(IVisitor visitor) { visitor.visit(this); } } public class CodingCourse extends Course { private int price; public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @Override public void accept(IVisitor visitor) { visitor.visit(this); } } public interface IVisitor { void visit(FreeCourse freeCourse); void visit(CodingCourse codingCourse); } public class Visitor implements IVisitor { /** * 訪問免費課程,打印所有免費課程名稱 * * @param freeCourse */ @Override public void visit(FreeCourse freeCourse) { System.out.println("免費課程:" + freeCourse.getName()); } /** * 訪問實戰(zhàn)課程,打印所有實戰(zhàn)課程名稱及價格 * * @param codingCourse */ @Override public void visit(CodingCourse codingCourse) { System.out.println("實戰(zhàn)課程:" + codingCourse.getName() + " 價格:" + codingCourse.getPrice() + "元"); } }
UML

測試
public class Test { public static void main(String[] args) { List<Course> courseList = new ArrayList<Course>(); FreeCourse freeCourse = new FreeCourse(); freeCourse.setName("SpringMVC數(shù)據(jù)綁定"); CodingCourse codingCourse = new CodingCourse(); codingCourse.setName("Java設計模式"); codingCourse.setPrice(299); courseList.add(freeCourse); courseList.add(codingCourse); for (Course course : courseList) { course.accept(new Visitor()); } } } ============輸出============= 免費課程:SpringMVC數(shù)據(jù)綁定 實戰(zhàn)課程:Java設計模式 價格:299元
- 說明:這個模式也很簡單,定義了一個免費課程類和實戰(zhàn)課程類,都繼承了課程抽象類,訪問者接口中有兩個visit方法,分別用于不同課程的訪問,其實現(xiàn)類中就是對應課程的訪問。它的核心是根據(jù)不同的visitor對相同的數(shù)據(jù)(都是Course)產(chǎn)生不同的操作行為
源碼中的應用
- 在日常中并不常用,如果遇到數(shù)據(jù)加載和數(shù)據(jù)分離的情況下,就可以考慮是否使用訪問者模式
- java.nio.file.FileVisitor:文件訪問者,通過它去遍歷文件樹會比較方便,比如查找文件夾內(nèi)符合一定條件的文件,或者按時間查看某一天創(chuàng)建的文件,它的實現(xiàn)就一個SimpleFileVisitor,如果里面的方法不能滿足我們的要求的話,可以繼承這個類,覆蓋里面的方法,或者自己寫一個FileVisitor的實現(xiàn)。
public interface FileVisitor<T> { FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs) throws IOException; FileVisitResult visitFile(T file, BasicFileAttributes attrs) throws IOException; FileVisitResult visitFileFailed(T file, IOException exc) throws IOException; FileVisitResult postVisitDirectory(T dir, IOException exc) throws IOException; }
- org.springframework.beans.factory.config.BeanDefinitionVisitor:Bean定義的訪問者,定義Bean的各種屬性,然后用里面的properties進行填充,這個類主要對Bean的各種數(shù)據(jù)進行分析把它們進行分解,比如下面這個visitBeanDefinition方法
public class BeanDefinitionVisitor { private StringValueResolver valueResolver; public BeanDefinitionVisitor(StringValueResolver valueResolver) { Assert.notNull(valueResolver, "StringValueResolver must not be null"); this.valueResolver = valueResolver; } public void visitBeanDefinition(BeanDefinition beanDefinition) { this.visitParentName(beanDefinition); this.visitBeanClassName(beanDefinition); this.visitFactoryBeanName(beanDefinition); this.visitFactoryMethodName(beanDefinition); this.visitScope(beanDefinition); this.visitPropertyValues(beanDefinition.getPropertyValues()); ConstructorArgumentValues cas = beanDefinition.getConstructorArgumentValues(); this.visitIndexedArgumentValues(cas.getIndexedArgumentValues()); this.visitGenericArgumentValues(cas.getGenericArgumentValues()); } }

浙公網(wǎng)安備 33010602011771號