【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)訪問者模式_第1頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)訪問者模式_第2頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)訪問者模式_第3頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)訪問者模式_第4頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)訪問者模式_第5頁(yè)
已閱讀5頁(yè),還剩6頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)訪問者模式

本篇文章給大家分享的是有關(guān)Android中怎么實(shí)現(xiàn)訪問者模式,在下覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著在下一起來看看吧。一、介紹訪問者模式是一種將數(shù)據(jù)操作與數(shù)據(jù)結(jié)構(gòu)分離的設(shè)計(jì)模式,它是《設(shè)計(jì)模式》中23種設(shè)計(jì)模式中最復(fù)雜的一個(gè),但它的使用頻率并不高,正如《設(shè)計(jì)模式》的作者GOF對(duì)訪問者模式的描述:大多數(shù)情況下,你不需要使用訪問者模式,但是當(dāng)你一旦需要使用它時(shí),那你就是真的需要它了。訪問者模式的基本想法是,軟件系統(tǒng)中擁有一個(gè)由許多對(duì)象構(gòu)成的、比較穩(wěn)定的對(duì)象結(jié)構(gòu),這些對(duì)象的類都擁有一個(gè)accept方法用來接受訪問者對(duì)象的訪問。訪問者是一個(gè)接口,它擁有一個(gè)visit方法,這個(gè)方法對(duì)訪問到的對(duì)象結(jié)構(gòu)中不同類型的元素作出不同的處理。在對(duì)象結(jié)構(gòu)的一次訪問過程中,我們遍歷整個(gè)對(duì)象結(jié)構(gòu),對(duì)每一個(gè)元素都實(shí)施accept方法,在每一個(gè)元素的accept方法中會(huì)調(diào)用訪問者的visit方法,從而使訪問者得以處理對(duì)象結(jié)構(gòu)的每一個(gè)元素,我們可以針對(duì)對(duì)象結(jié)構(gòu)設(shè)計(jì)不同的訪問者類來完成不同的操作,達(dá)到區(qū)別對(duì)待的效果。二、定義封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素的操作,它可以在不改變這個(gè)數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作。三、使用場(chǎng)景對(duì)象結(jié)構(gòu)比較穩(wěn)定,但經(jīng)常需要在此對(duì)象結(jié)構(gòu)上定義新的操作。需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的對(duì)象進(jìn)行很多不同的并且不相關(guān)的操作,而需要避免這些操作”污染“這些對(duì)象的類,也不希望在增加新操作時(shí)修改這些類。四、訪問者模式的UML類圖UML類圖:角色介紹:Visitor:接口或抽象類,定義了對(duì)每一個(gè)元素的訪問行為,參數(shù)就是可訪問的元素,方法個(gè)數(shù)理論上是個(gè)元素個(gè)數(shù)一樣的。因此,訪問者模式要求被訪問的對(duì)象結(jié)構(gòu)要穩(wěn)定,如果經(jīng)常增刪元素,必然會(huì)導(dǎo)致頻繁修改Visitor接口,就不適合用訪問者模式了。ConcreteVisitor:具體的訪問者,定義具體的對(duì)每一個(gè)元素的具體訪問行為。Element:抽象的元素接口或抽象類,定義了一個(gè)接待訪問者的方法,讓每個(gè)元素都可以被訪問者訪問。ElementA,ElementB:具體的元素類,提供接收訪問方法的具體實(shí)現(xiàn)。這個(gè)具體實(shí)現(xiàn)通常是調(diào)用訪問者提供的訪問該元素的方法。ObjectStructure:定義對(duì)象結(jié)構(gòu),里面維護(hù)了一個(gè)元素的集合,并且迭代這些元素供訪問者訪問。五、簡(jiǎn)單示例情景:年終了,公司會(huì)給員工進(jìn)行業(yè)績(jī)考核。但是,不同領(lǐng)域的管理人員對(duì)于員工的評(píng)定標(biāo)準(zhǔn)不一樣?,F(xiàn)在員工有工程師和經(jīng)理,評(píng)定者有CEO和CTO,我們假定CTO只關(guān)注工程師的代碼量、經(jīng)理的新產(chǎn)品數(shù)量,而CEO關(guān)注的是工程師的KPI和經(jīng)理的KPI以及新產(chǎn)品數(shù)量。員工基類:/**

*

員工基類(Element)

*/

public

abstract

class

Staff

{

//員工姓名

public

String

name;

//員工KPI

public

int

kpi;

public

Staff(String

name)

{

super();

=

name;

this.kpi

=

new

Random().nextInt(10);

}

//接受Visitor的訪問

public

abstract

void

accept(Visitor

visitor);

}工程師:/**

*

工程師

*/

public

class

Engineer

extends

Staff{

private

int

codeLines;//代碼數(shù)量

public

Engineer(String

name)

{

super(name);

codeLines

=

new

Random().nextInt(10

*

10000);

}

@Override

public

void

accept(Visitor

visitor)

{

visitor.visit(this);

}

//工程師這一年寫的代碼數(shù)量

public

int

getCodeLines(){

return

codeLines;

}

}經(jīng)理:/**

*

經(jīng)理

*/

public

class

Manager

extends

Staff{

private

int

products;//產(chǎn)品數(shù)量

public

Manager(String

name)

{

super(name);

products

=

new

Random().nextInt(10);

}

@Override

public

void

accept(Visitor

visitor)

{

visitor.visit(this);

}

//一年內(nèi)做的產(chǎn)品數(shù)量

public

int

getProducts(){

return

products;

}

}Visitor類:public

interface

Visitor

{

/**

*

訪問工程師類型

*/

public

void

visit(Engineer

engineer);

/**

*

訪問經(jīng)理類型

*/

public

void

visit(Manager

manager);

}CEO訪問者:public

class

CEOVisitor

implements

Visitor

{

@Override

public

void

visit(Engineer

engineer)

{

System.out.println("工程師:"

+

+

",

KPI:"

+

engineer.kpi);

}

@Override

public

void

visit(Manager

manager)

{

System.out.println("經(jīng)理:"

+

+

",

KPI:"

+

manager.kpi

+

",

新產(chǎn)品數(shù)量

:"

+

manager.getProducts());

}

}CTO訪問者:public

class

CTOVisitor

implements

Visitor

{

@Override

public

void

visit(Engineer

engineer)

{

System.out.println("工程師:"

+

+

",

代碼數(shù)量:"

+

engineer.getCodeLines());

}

@Override

public

void

visit(Manager

manager)

{

System.out.println("經(jīng)理:"

+

+",

產(chǎn)品數(shù)量

:"

+

manager.getProducts());

}

}員工報(bào)表://員工業(yè)務(wù)報(bào)表類(ObjectStructure)

public

class

BusinessReport

{

List<Staff>

mStaffs

=

new

LinkedList<Staff>();

public

BusinessReport()

{

mStaffs.add(new

Manager("王經(jīng)理"));

mStaffs.add(new

Engineer("工程師-A"));

mStaffs.add(new

Engineer("工程師-B"));

mStaffs.add(new

Manager("李經(jīng)理"));

mStaffs.add(new

Engineer("工程師-C"));

}

/**

*

為訪問者展示報(bào)表

*

@param

visitor

如CEO、CTO

*/

public

void

showReport(Visitor

visitor){

for(Staff

staff

:

mStaffs){

staff.accept(visitor);

}

}

}Client訪問:public

class

Client

{

public

static

void

main(String[]

args)

{

//構(gòu)建報(bào)表

BusinessReport

report

=

new

BusinessReport();

System.out.println("=====

給CEO看報(bào)表

=====");

//設(shè)置訪問者CEO

report.showReport(new

CEOVisitor());

System.out.println("=====

給CTO看報(bào)表

=====");

//設(shè)置訪問者CTO

report.showReport(new

CTOVisitor());

}

}結(jié)果:=====

給CEO看報(bào)表

=====

經(jīng)理:王經(jīng)理,

KPI:2,

新產(chǎn)品數(shù)量

:5

工程師:工程師-A,

KPI:5

工程師:工程師-B,

KPI:7

經(jīng)理:李經(jīng)理,

KPI:9,

新產(chǎn)品數(shù)量

:8

工程師:工程師-C,

KPI:1

=====

給CTO看報(bào)表

=====

經(jīng)理:王經(jīng)理,

產(chǎn)品數(shù)量

:5

工程師:工程師-A,

代碼數(shù)量:26238

工程師:工程師-B,

代碼數(shù)量:8282

經(jīng)理:李經(jīng)理,

產(chǎn)品數(shù)量

:8

工程師:工程師-C,

代碼數(shù)量:47927從上面代碼中可以看出,如果要增加一個(gè)訪問者,你新創(chuàng)建一個(gè)實(shí)現(xiàn)了Visitor接口的類,然后實(shí)現(xiàn)兩個(gè)visit方法來對(duì)不同的元素進(jìn)行不同的操作,從而達(dá)到數(shù)據(jù)對(duì)象與數(shù)據(jù)操作相分離的效果。如果不使用訪問者模式,而又想對(duì)不同元素進(jìn)行不同的操作,那么必定會(huì)使用if-else和類型轉(zhuǎn)換,這使得代碼難以升級(jí)維護(hù)。六、Android中的訪問者模式安卓中的著名開源庫(kù)ButterKnife、Dagger、Retrofit都是基于APT(AnnotationProcessingTools)實(shí)現(xiàn)。而編譯注解核心依賴APT。當(dāng)我們通過APT處理注解時(shí),最終會(huì)將獲取到的元素轉(zhuǎn)換為相應(yīng)的Element元素,以便獲取到它們對(duì)應(yīng)信息。那么元素基類的源碼如下:(路徑:javax.lang.model.element.Element)public

interface

Element

extends

javax.lang.model.AnnotatedConstruct

{

/**

*

Returns

the

{@code

kind}

of

this

element.

*

*

@return

the

kind

of

this

element

*/

ElementKind

getKind();//獲取元素類型

//代碼省略

/**

*

Applies

a

visitor

to

this

element.

*

*

@param

<R>

the

return

type

of

the

visitor's

methods

*

@param

<P>

the

type

of

the

additional

parameter

to

the

visitor's

methods

*

@param

v

the

visitor

operating

on

this

element

*

@param

p

additional

parameter

to

the

visitor

*

@return

a

visitor-specified

result

*/

<R,

P>

R

accept(ElementVisitor<R,

P>

v,

P

p);//接受訪問者的訪問

}ElementVisitor就是訪問者類型,ElementVisitor源碼如下:public

interface

ElementVisitor<R,

P>

{

/**

*

Visits

an

element.

*

@param

e

the

element

to

visit

*

@param

p

a

visitor-specified

parameter

*

@return

a

visitor-specified

result

*/

R

visit(Element

e,

P

p);

/**

*

A

convenience

method

equivalent

to

{@code

v.visit(e,

null)}.

*

@param

e

the

element

to

visit

*

@return

a

visitor-specified

result

*/

R

visit(Element

e);

/**

*

Visits

a

package

element.

*

@param

e

the

element

to

visit

*

@param

p

a

visitor-specified

parameter

*

@return

a

visitor-specified

result

*/

R

visitPackage(PackageElement

e,

P

p);

/**

*

Visits

a

type

element.

*

@param

e

the

element

to

visit

*

@param

p

a

visitor-specified

parameter

*

@return

a

visitor-specified

result

*/

R

visitType(TypeElement

e,

P

p);

/**

*

Visits

a

variable

element.

*

@param

e

the

element

to

visit

*

@param

p

a

visitor-specified

parameter

*

@return

a

visitor-specified

result

*/

R

visitVariable(VariableElement

e,

P

p);

/**

*

Visits

an

executable

element.

*

@param

e

the

element

to

visit

*

@param

p

a

visitor-specified

parameter

*

@return

a

visitor-specified

result

*/

R

visitExecutable(ExecutableElement

e,

P

p);

/**

*

Visits

a

type

parameter

element.

*

@param

e

the

element

to

visit

*

@param

p

a

visitor-specified

parameter

*

@return

a

visitor-specified

result

*/

R

visitTypeParameter(TypeParameterElement

e,

P

p);

/**

*

Visits

an

unknown

kind

of

element.

*

This

can

occur

if

the

language

evolves

an

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論