Android 訪問者模式

Android 23種設(shè)計(jì)模式

前言

訪問者模式是一種把數(shù)據(jù)操作與數(shù)據(jù)結(jié)構(gòu)分離的設(shè)計(jì)模式。通常適用于:
1、對(duì)象的結(jié)構(gòu)比較穩(wěn)定,但又經(jīng)常要在這個(gè)對(duì)象上定義新的操作。
2、需要對(duì)一個(gè)對(duì)象進(jìn)行很多不同且不相關(guān)的操作,而需要避免這些操作污染這個(gè)對(duì)象類。也不希望在增加新的操作時(shí),修改原本的類。
這種設(shè)計(jì)模式相對(duì)復(fù)雜,而當(dāng)你需要用到訪問者模式的時(shí)候,這個(gè)模式就很必要了。

訪問者模式定義

表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素類的前提下,定義作用于這些元素的新操作。

例子

我們通過一個(gè)例子來(lái)學(xué)習(xí)理解什么是訪問者模式。這是一個(gè)老師訪問學(xué)生成績(jī)的例子。

1、被訪問者

首先我們定義被訪問者學(xué)生。抽象了一個(gè)學(xué)生基類,隨機(jī)數(shù)來(lái)模擬總成績(jī)。

public abstract class Students {
    public String name;
    public int totalScore; // 總成績(jī)
    Students(String aName) {
        name = aName;
        totalScore = new Random().nextInt(100);
    }
    public abstract void accept(Visitor visitor);
}

然后我們定義了兩種學(xué)生,當(dāng)然你可以定義多種。

// 體育生,隨機(jī)數(shù)模擬成績(jī)
public class SportsStudents extends Students {
    public int sports;

    public SportsStudents(String aName) {
        super(aName);
        sports = new Random().nextInt(100);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 美術(shù)生,隨機(jī)數(shù)模擬成績(jī)
public class ArtStudents extends Students {
    public int art;

    public ArtStudents(String aName) {
        super(aName);
        art = new Random().nextInt(100);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

代碼很簡(jiǎn)單就是模擬了一下成績(jī),我們可以看到被訪問者學(xué)生,這個(gè)類很穩(wěn)定。不需要再添加其他信息來(lái)“污染”被訪問者了。

2、訪問者

先抽象出訪問者的訪問方法visit

public interface Visitor {
    public void visit(ArtStudents artStudents);
    public void visit(SportsStudents sportsStudents);
}

這里定義兩個(gè)訪問者,一個(gè)班主任,他關(guān)注總成績(jī)和特長(zhǎng)科目成績(jī)。另一個(gè)特長(zhǎng)老師,他只關(guān)心特長(zhǎng)科目成績(jī)。

// 班主任
public class HeadmasterTeacherVisitor implements Visitor {
    private static String TAG = ArtStudents.class.getSimpleName();
    @Override
    public void visit(ArtStudents artStudents) {
        Log.d(TAG,"name = " + artStudents.name);
        Log.d(TAG,"totalScore = " + artStudents.totalScore);
        Log.d(TAG,"art = " + artStudents.art);
    }

    @Override
    public void visit(SportsStudents sportsStudents) {
        Log.d(TAG,"name = " + sportsStudents.name);
        Log.d(TAG,"totalScore = " + sportsStudents.totalScore);
        Log.d(TAG,"sports = " + sportsStudents.sports);
    }
}

// 特長(zhǎng)老師
public class SpecialTeacherVisitor implements Visitor {
    private static String TAG = SpecialTeacherVisitor.class.getSimpleName();
    @Override
    public void visit(ArtStudents artStudents) {
        Log.d(TAG,"name = " + artStudents.name);
        Log.d(TAG,"art = " + artStudents.art);
    }

    @Override
    public void visit(SportsStudents sportsStudents) {
        Log.d(TAG,"name = " + sportsStudents.name);
        Log.d(TAG,"sports = " + sportsStudents.sports);
    }
}

訪問者就比較直觀,目的明確,訪問者只關(guān)注他想關(guān)注的信息,不需要多于的操作。這里體現(xiàn)了訪問操作的不同且不相關(guān)。

3、訪問

訪問者和被訪問者我們寫完了。然后我們寫如何訪問。訪問的核心就是一個(gè)遍歷。根據(jù)不同的訪問者和被訪問者達(dá)到不同的操作目的。
先遍歷

public class StudentsList {
    List<Students> list = new LinkedList<Students>();
    public StudentsList() {
        list.add(new ArtStudents("jack"));
        list.add(new ArtStudents("john"));
        list.add(new SportsStudents("lily"));
        list.add(new SportsStudents("sky"));
    }

    public void showStudentschievement(Visitor visitor) {
        for (Students students : list) {
            students.accept(visitor);
        }
    }
}

這里模擬把所有學(xué)生放到一個(gè)list里面。遍歷的時(shí)候,被訪問者students調(diào)用accept訪問來(lái)同意訪問。記得前文的accept方法里就是調(diào)用Visitor.visit方法而已。所以我們看最后如何調(diào)用

4、調(diào)用

StudentsList list = new StudentsList();
 list.showStudentschievement(new HeadmasterTeacherVisitor());
list.showStudentschievement(new SpecialTeacherVisitor());

看輸出結(jié)果:

01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: name = jack
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: totalScore = 13
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: art = 52
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: name = john
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: totalScore = 98
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: art = 12
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: name = lily
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: totalScore = 51
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: sports = 23
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: name = sky
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: totalScore = 24
01-21 14:37:31.729 26555-26555/com.yink.designpattern.designpattern D/ArtStudents: sports = 30
01-21 14:37:31.739 26555-26555/com.yink.designpattern.designpattern D/SpecialTeacherVisitor: name = jack
01-21 14:37:31.739 26555-26555/com.yink.designpattern.designpattern D/SpecialTeacherVisitor: art = 52
01-21 14:37:31.739 26555-26555/com.yink.designpattern.designpattern D/SpecialTeacherVisitor: name = john
01-21 14:37:31.739 26555-26555/com.yink.designpattern.designpattern D/SpecialTeacherVisitor: art = 12
01-21 14:37:31.739 26555-26555/com.yink.designpattern.designpattern D/SpecialTeacherVisitor: name = lily
01-21 14:37:31.739 26555-26555/com.yink.designpattern.designpattern D/SpecialTeacherVisitor: sports = 23
01-21 14:37:31.739 26555-26555/com.yink.designpattern.designpattern D/SpecialTeacherVisitor: name = sky
01-21 14:37:31.739 26555-26555/com.yink.designpattern.designpattern D/SpecialTeacherVisitor: sports = 30

訪問者模式小結(jié)

訪問者模式核心有如下,記住這三點(diǎn)理解何為訪問者模式:
1、被訪問者不變。
2、根據(jù)訪問者和被訪問者的不同,兩兩對(duì)應(yīng)達(dá)到不同的目的。
3、遍歷被訪問者實(shí)現(xiàn)“訪問”。

總結(jié)

最后抖下訪問者模式的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1、各角色職責(zé)分離,符合單一原則
2、擴(kuò)展十分方便,靈活
3、數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu)上的操作解耦
缺點(diǎn):
1、被訪問者對(duì)訪問者公布了細(xì)節(jié),違反迪米特原則
2、被訪問者要改動(dòng)的時(shí)候,修改十分麻煩。
3、訪問者和被訪者為了達(dá)到不同的行為目的的時(shí)候,為了區(qū)分依賴了類的不同,沒有依賴抽象。

所以不光是其它模式還是訪問者模式,我們都要根據(jù)具體的情況來(lái)評(píng)估我們是否真的需要這種設(shè)計(jì)模式。這里的訪問者模式就得十分注意我們的被訪問者是否真的足夠穩(wěn)定。所以一定要多思考,明確它的使用場(chǎng)景。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容