六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

深入淺出Java的訪問(wèn)者模式

[摘要]一、引子   對(duì)于系統(tǒng)中一個(gè)已經(jīng)完成的類(lèi)層次結(jié)構(gòu),我們已經(jīng)給它提供了滿足需求的接口。但是面對(duì)新增加的需求,我們應(yīng)該怎么做呢?如果這是為數(shù)不多的幾次變動(dòng),而且你不用為了一個(gè)需求的調(diào)整而將整個(gè)類(lèi)層次結(jié)構(gòu)統(tǒng)統(tǒng)地修改一遍,那么直接在原有類(lèi)層次結(jié)構(gòu)上修改也許是個(gè) 不錯(cuò) 的主意。   但是往往我們遇到的卻是:...
一、引子

  對(duì)于系統(tǒng)中一個(gè)已經(jīng)完成的類(lèi)層次結(jié)構(gòu),我們已經(jīng)給它提供了滿足需求的接口。但是面對(duì)新增加的需求,我們應(yīng)該怎么做呢?如果這是為數(shù)不多的幾次變動(dòng),而且你不用為了一個(gè)需求的調(diào)整而將整個(gè)類(lèi)層次結(jié)構(gòu)統(tǒng)統(tǒng)地修改一遍,那么直接在原有類(lèi)層次結(jié)構(gòu)上修改也許是個(gè) 不錯(cuò) 的主意。

  但是往往我們遇到的卻是:這樣的需求變動(dòng)也許會(huì)不停的發(fā)生;更重要的是需求的任何變動(dòng)可能都要讓你將整個(gè)類(lèi)層次結(jié)構(gòu)修改個(gè)底朝天……。這種類(lèi)似的操作分布在不同的類(lèi)里面,不是一個(gè)好現(xiàn)象,我們要對(duì)這個(gè)結(jié)構(gòu)重構(gòu)一下了。

  那么,訪問(wèn)者模式也許是你很好的選擇。

   二、定義與結(jié)構(gòu)

  訪問(wèn)者模式,顧名思義使用了這個(gè)模式后就可以在不修改已有程序結(jié)構(gòu)的前提下,通過(guò)添加額外的“訪問(wèn)者”來(lái)完成對(duì)已有代碼功能的提升。

  《設(shè)計(jì)模式》一書(shū)對(duì)于訪問(wèn)者模式給出的定義為:表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素的類(lèi)的前提下定義作用于這些元素的新操作。從定義可以看出結(jié)構(gòu)對(duì)象是使用訪問(wèn)者模式必須條件,而且這個(gè)結(jié)構(gòu)對(duì)象必須存在遍歷自身各個(gè)對(duì)象的方法。這便類(lèi)似于java中的collection概念了。

  以下是訪問(wèn)者模式的組成結(jié)構(gòu):

  1) 訪問(wèn)者角色(Visitor):為該對(duì)象結(jié)構(gòu)中具體元素角色聲明一個(gè)訪問(wèn)操作接口。該操作接口的名字和參數(shù)標(biāo)識(shí)了發(fā)送訪問(wèn)請(qǐng)求給具體訪問(wèn)者的具體元素角色。這樣訪問(wèn)者就可以通過(guò)該元素角色的特定接口直接訪問(wèn)它。

  2) 具體訪問(wèn)者角色(Concrete Visitor):實(shí)現(xiàn)每個(gè)由訪問(wèn)者角色(Visitor)聲明的操作。

  3) 元素角色(Element):定義一個(gè)Accept操作,它以一個(gè)訪問(wèn)者為參數(shù)。

  4) 具體元素角色(Concrete Element):實(shí)現(xiàn)由元素角色提供的Accept操作。

  5) 對(duì)象結(jié)構(gòu)角色(Object Structure):這是使用訪問(wèn)者模式必備的角色。它要具備以下特征:能枚舉它的元素;可以提供一個(gè)高層的接口以允許該訪問(wèn)者訪問(wèn)它的元素;可以是一個(gè)復(fù)合(組合模式)或是一個(gè)集合,如一個(gè)列表或一個(gè)無(wú)序集合。

  來(lái)張類(lèi)圖就能更加清晰的看清訪問(wèn)者模式的結(jié)構(gòu)了。

深入淺出Java的訪問(wèn)者模式

  那么像引言中假想的。我們應(yīng)該做些什么才能讓訪問(wèn)者模式跑起來(lái)呢?首先我們要在原有的類(lèi)層次結(jié)構(gòu)中添加accept方法。然后將這個(gè)類(lèi)層次中的類(lèi)放到一個(gè)對(duì)象結(jié)構(gòu)中去。這樣再去創(chuàng)建訪問(wèn)者角色……

   三、舉例

  本人閱歷實(shí)在可憐,沒(méi)能找到訪問(wèn)者模式在實(shí)際應(yīng)用中的例子。只好借《Thinking in Patterns with java》中的教學(xué)代碼一用。我稍微做了下修改。

import java.util.*;
import junit.framework.*;

//訪問(wèn)者角色

interface Visitor {
 void visit(Gladiolus g);
 void visit(Runuculus r);
 void visit(Chrysanthemum c);
}

// The Flower hierarchy cannot be changed:
//元素角色

interface Flower {
 void accept(Visitor v);
}

//以下三個(gè)具體元素角色

class Gladiolus implements Flower {
 public void accept(Visitor v) { v.visit(this);}
}

class Runuculus implements Flower {
 public void accept(Visitor v) { v.visit(this);}
}

class Chrysanthemum implements Flower {
 public void accept(Visitor v) { v.visit(this);}
}

// Add the ability to produce a string:
//實(shí)現(xiàn)的具體訪問(wèn)者角色

class StringVal implements Visitor {
 String s;
 public String toString() { return s; }
 public void visit(Gladiolus g) {
  s = "Gladiolus";
 }

 public void visit(Runuculus r) {
  s = "Runuculus";
 }

 public void visit(Chrysanthemum c) {
  s = "Chrysanthemum";
 }
}

// Add the ability to do "Bee" activities:
//另一個(gè)具體訪問(wèn)者角色

class Bee implements Visitor {
 public void visit(Gladiolus g) {
  System.out.println("Bee and Gladiolus");
 }

 public void visit(Runuculus r) {
  System.out.println("Bee and Runuculus");
 }

 public void visit(Chrysanthemum c) {
  System.out.println("Bee and Chrysanthemum");
 }
}

//這是一個(gè)對(duì)象生成器
//這不是一個(gè)完整的對(duì)象結(jié)構(gòu),這里僅僅是模擬對(duì)象結(jié)構(gòu)中的元素

class FlowerGenerator {
 private static Random rand = new Random();
 public static Flower newFlower() {
   switch (rand.nextInt(3)) {
  default:
   case 0: return new Gladiolus(); 
   case 1: return new Runuculus();
   case 2: return new Chrysanthemum();
  }
 }
}

//客戶 測(cè)試程序

public class BeeAndFlowers extends TestCase {

 /*
  在這里你能看到訪問(wèn)者模式執(zhí)行的流程:
  首先在客戶端先獲得一個(gè)具體的訪問(wèn)者角色
  遍歷對(duì)象結(jié)構(gòu)
  對(duì)每一個(gè)元素調(diào)用accept方法,將具體訪問(wèn)者角色傳入
  這樣就完成了整個(gè)過(guò)程
 */
 //對(duì)象結(jié)構(gòu)角色在這里才 組裝 上

 List flowers = new ArrayList();
 public BeeAndFlowers() {
  for(int i = 0; i < 10; i++)
   flowers.add(FlowerGenerator.newFlower());
 }

 Visitor sval ;
 public void test() {
  // It’s almost as if I had a function to
  // produce a Flower string representation:
  //這個(gè)地方你可以修改以便使用另外一個(gè)具體訪問(wèn)者角色

  sval = new StringVal();
  Iterator it = flowers.iterator();
  while(it.hasNext()) {
   ((Flower)it.next()).accept(sval);
   System.out.println(sval);
  }
 }

 public static void main(String args[]) {
  junit.textui.TestRunner.run(BeeAndFlowers.class);
 }

}
   四、雙重分派

  對(duì)了,你在上面的例子中體會(huì)到雙重分派的實(shí)現(xiàn)了沒(méi)有?

  首先在客戶程序中將具體訪問(wèn)者模式作為參數(shù)傳遞給具體元素角色(加亮的地方所示)。這便完成了一次分派。

  進(jìn)入具體元素角色后,具體元素角 色調(diào) 用作為參數(shù)的具體訪問(wèn)者模式中的visitor方法,同時(shí)將自己(this)作為參數(shù)傳遞進(jìn)去。具體訪問(wèn)者模式再根據(jù)參數(shù)的不同來(lái)選擇方法來(lái)執(zhí)行(加亮的地方所示)。這便完成了第二次分派。

   五、優(yōu)缺點(diǎn)及適用情況

  先來(lái)看下訪問(wèn)者模式的使用能否避免引言中的痛苦。使用了訪問(wèn)者模式以后,對(duì)于原來(lái)的類(lèi)層次增加新的操作,僅僅需要實(shí)現(xiàn)一個(gè)具體訪問(wèn)者角色就可以了,而不必修改整個(gè)類(lèi)層次。而且這樣符合“開(kāi)閉原則”的要求。而且每個(gè)具體的訪問(wèn)者角色都對(duì)應(yīng)于一個(gè)相關(guān)操作,因此如果一個(gè)操作的需求有變,那么僅僅修改一個(gè)具體訪問(wèn)者角色,而不用改動(dòng)整個(gè)類(lèi)層次。

  看來(lái)訪問(wèn)者模式確實(shí)能夠解決我們面臨的一些問(wèn)題。

  而且由于訪問(wèn)者模式為我們的系統(tǒng)多提供了一層“訪問(wèn)者”,因此我們可以在訪問(wèn)者中添加一些對(duì)元素角色的額外操作。

  但是“開(kāi)閉原則”的遵循總是片面的。如果系統(tǒng)中的類(lèi)層次發(fā)生了變化,會(huì)對(duì)訪問(wèn)者模式產(chǎn)生什么樣的影響呢?你必須修改訪問(wèn)者角色和每一個(gè)具體訪問(wèn)者角色……

  看來(lái)訪問(wèn)者角色不適合具體元素角色經(jīng)常發(fā)生變化的情況。而且訪問(wèn)者角色要執(zhí)行與元素角色相關(guān)的操作,就必須讓元素角色將自己內(nèi)部屬性暴露出來(lái),而在java中就意味著其它的對(duì)象也可以訪問(wèn)。這就破壞了元素角色的封裝性。而且在訪問(wèn)者模式中,元素與訪問(wèn)者之間能夠傳遞的信息有限,這往往也會(huì)限制訪問(wèn)者模式的使用。

  《設(shè)計(jì)模式》一書(shū)中給出了訪問(wèn)者模式適用的情況:

  1) 一個(gè)對(duì)象結(jié)構(gòu)包含很多類(lèi)對(duì)象,它們有不同的接口,而你想對(duì)這些對(duì)象實(shí)施一些依賴于其具體類(lèi)的操作。

  2) 需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的對(duì)象進(jìn)行很多不同的并且不相關(guān)的操作,而你想避免讓這些操作“污染”這些對(duì)象的類(lèi)。Visitor使得你可以將相關(guān)的操作集中起來(lái)定義在一個(gè)類(lèi)中。

  3) 當(dāng)該對(duì)象結(jié)構(gòu)被很多應(yīng)用共享時(shí),用Visitor模式讓每個(gè)應(yīng)用僅包含需要用到的操作。

  4) 定義對(duì)象結(jié)構(gòu)的類(lèi)很少改變,但經(jīng)常需要在此結(jié)構(gòu)上定義新的操作。改變對(duì)象結(jié)構(gòu)類(lèi)需要重定義對(duì)所有訪問(wèn)者的接口,這可能需要很大的代價(jià)。如果對(duì)象結(jié)構(gòu)類(lèi)經(jīng)常改變,那么可能還是在這些類(lèi)中定義這些操作較好。

  你是否能很好的理解呢?

   六、總結(jié)

  這是一個(gè)巧妙而且復(fù)雜的模式,它的使用條件比較苛刻。當(dāng)系統(tǒng)中存在著固定的數(shù)據(jù)結(jié)構(gòu)(比如上面的類(lèi)層次),而有著不同的行為,那么訪問(wèn)者模式也許是個(gè)不錯(cuò)的選擇。



主站蜘蛛池模板: 伊人色婷婷综在合线亚洲 | 午夜在线观看免费影院 | 午夜天堂在线视频 | 四虎永久免费地址在线网站 | 欧美太黄太色视频在线观看 | 天堂网欧美 | 日韩精品第一区 | 一区二区三区在线视频播放 | 色网站网址| 日本三级2020 | 午夜免费体验 | 日本人亚洲人成人 | 日韩中文字幕高清在线专区 | 日韩欧美国产三级 | 啪啪午夜 | 手机看片福利盒子久久青 | 欧美一级免费大片 | 午夜高清 | 香蕉久草 | 青苹果a4yy私人毛片 | 天天躁夜夜躁狠狠躁2021a | 中文字幕在线观看第一页 | 亚洲精品色婷婷在线影院麻豆 | 天天操天天干天天拍 | 色成人亚洲 | 日韩高清中文字幕 | 亚洲伊人久久大香线焦 | 性生活国产 | 午夜激情影院 | 日本mv精品中文字幕 | 欧美性第一页 | 青草香蕉视频 | 色噜噜狠狠网站 | 综合网色 | 四虎国产精品永久在线看 | 日本xxx在线观看免费播放 | 四虎在线视频免费观看 | 四虎精品成人免费观看 | 日本亚洲乱码中文字幕影院 | 一二三四高清在线手机视频 | 青春草在线免费观看 |