簡體   English   中英

java中的訪問者模式實現 - 這看起來如何?

[英]Visitor pattern implementation in java- How does this look?

Alrite,我會直接跳到代碼:

public interface Visitor {

public void visitInventory(); 
public void visitMaxCount();
public void visitCountry();
public void visitSomethingElse();
public void complete();
//the idea of this visitor is that when a validator would visit it, it would validate data
//when a persister visits it, it would persist data, etc, etc.
// not sure if I making sense here...
}

public interface Visitable {
public void accept(Visitor visitor); 
}

這是一個基礎實現:

public class StoreValidator implements Visitor {
private List <ValidationError> storeValidationErrors = new ArrayList<ValidationError>();

public void addError(ValidationError error) {
storeValidationErrors.add(error);
}

public List<ValidationError> getErrors() {
return storeValidationErrors;
}

public void visitInventory() {
// do nothing 
}

public void visitMaxCount() {
//do nothing
}
//... etc..  all empty implementations 

}

你會明白為什么我在這里做了一個空的實現...我現在會寫一個驗證器..它擴展了StoreValidator

public XYZValidator extends StoreValidator {

@Override 
public void visitInventory(Visitable visitable) { 
// do something with visitable .. cast it to expected type
// invoke a DAO, obtain results from DB
// if errors found, do addError(new ValidationError()); with msg.
}

@Override 
public void visitMaxCount(Visitable visitable) {
//do something with visitable.. 
}

// I wouldn't implement the rest coz they wouldn't make sense
// in XYZValidator.. so they are defined as empty in StoreValidator.

}

現在這是一個可訪問的樣子:

public Store implements Visitable {

public void accept(Visitor visitor) {
visitor.visitInventory();
visitor.visitMaxCount();
}
}

我可以在Store對象列表中使用類似的代碼:

List<Store> stores; //assume this has a list of stores.
StoreValidator validator = new XYZValidator(); //or I would get it from a validatorfactory
for(Store store: stores) {
           store.accept(validator); // so even if you send a wrong validator, you are good.
}

類似地,您將擁有ABCValidator,它將為其他方法(visitCountry / visitSomethinElse)提供實現,並且它將從StoreValidator擴展。 我會有另一種類型的Object(而不是Store)定義accept方法。

我確實在這里看到一個問題...說,我需要一個與StoreValidator不同的FileValidator,我希望它沒有這些與業務相關的驗證,例如visitInventory()等。但是,通過擁有單個接口Visitor,我最終會在Visitor接口中聲明各種方法。 那是對的嗎? 這是你怎么做的?

我不知道我的模式是否錯誤,或者我是否有任何意義。 請分享你的想法。

前段時間我為我的碩士論文寫了類似的東西。 此代碼比您的代碼略微安全:

interface Visitable<T extends Visitor> {

   void acceptVisitor(T visitor);
}

interface Visitor {

    /**
     * Called before any other visiting method.
     */
    void startVisit();

    /**
     * Called at the end of the visit. 
     */
    void endVisit();
}

例:

interface ConstantPoolVisitor extends Visitor {

    void visitUTF8(int index, String utf8);

    void visitClass(int index, int utf8Index);

    // ==cut==
}

class ConstantPool implements Visitable<ConstantPoolVisitor> {

    @Override
    public void acceptVisitor(ConstantPoolVisitor visitor) {
        visitor.startVisit();

        for (ConstanPoolEntry entry : entries) {
            entry.acceptVisitor(visitor);
        }

        visitor.endVisit();
    }

所以是的,我認為這絕對是一個良好而靈活的設計,如果且僅當您的數據變化慢於您的行為時。 在我的示例中,數據是Java字節碼,它是固定的(由JVM規范定義)。 當“行為支配”(我想轉儲,編譯,轉換,重構等我的字節碼)時,訪問者模式允許您更改/添加/刪除行為而不觸及您的數據類。 只需添加另一個Visitor實現。

為簡單起見,假設我必須在訪問者界面中添加另一個訪問方法:我最終會破壞所有代碼。

作為替代方案,我會考慮這種情況的策略模式 策略+裝飾器是一個很好的驗證設計。

您的代碼存在問題。 您提供的界面有如下方法

public void visitInventory(); 

但是你然后在XYZValidator中實現它

public void visitInventory(Visitable visitable)

訪問者模式是一種在不自動執行此操作的語言(例如Java)中實現多個調度的方法。 其中一個要求是您有一組相關的類(即一組具有單個超類的子類)。 你沒有這里,所以訪客模式不合適。 但是,您嘗試執行的任務很好,它不是訪問者模式。

在Java中,如果您有類似的代碼,您應該考慮訪問者模式

public void count(Item item) {
  if (item instanceof SimpleItem) {
    // do something
  } else if (item instanceof ComplexItem {
    // do something else
  } else ...
}

特別是如果Item的子類相對固定。

我以不同的方式使用訪問者模式。我有一個特定的訪問者接口,用於某種類型的對象,這個接口只聲明一個方法 - 用於訪問該對象..像這樣:

public interface TreeNodeVisitor {
    void visit(TreeNode node);
}

對象TreeNode可以接受TreeNodeVisitor ,這意味着他只是調用它的節點和/或它的子節點的訪問方法。

訪問者的具體實現實現了訪問方法並說明訪問者將做什么...例如ContryVisitor,InventoryVisitor等

這種方法應該避免你的問題..

您可能不希望將模式直接映射到該模式后面的所有內容實現的單個接口。 模式不是接口,它們是實現解決方案的一般計划。

在您的示例中,您將為希望在適當情況下使用訪問者模式的不同業務對象創建StoreVisitor接口和FileVisitor接口。

可能是不同的Visitor實現共享公共活動 - 因此您可以使用定義這些常用功能的超接口。 然后,您可以將可訪問接口編碼為使用特定的Visitable接口或適當的超類。

例如,FileVisitor和SQLTableVisitor接口可能是DataStoreVisitor接口的子類。 然后:

VisitableStore接受StoreVisitor,

VisitableFile接受Filevisitor,或

VisitableDataStore接受DataStoreVistor(可能是FileVisitor或SQLTableVisitor的實現)。

  • 原諒隨機的例子,我希望這是有道理的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM