2012-11-22 77 views
0

我有以下代碼和體系結構(實際上這是一個非常簡化的版本)的抽象和具體類的consting。獲取數據到回調方法

public abstract class AbstractProcessor { 
    public void updateDataFromUrl(String url) { 
     //Download url 
     //Decrypt, and do a lot of stuff, 
     String data = "abc"; //Result from downloading 

     String processed = processData(data); 

     //Do a lot of other things with the transformed data 
    } 

    public abstract String processData(String data); 
} 


final class ConcreteProcessor extends AbstractProcessor { 
    public void updateData(int year, int month, int day) { 
     String url = String.format("http://%d.%d.%d", year, month, day); 
     updateDataFromUrl(url); 
    } 

    @Override 
    public String processData(String data) { 
     //Process the data 

     //--------------- 
     //PROBLEM: 
     //---------------- 
     //Need access to year, month, day .... 

     return null; 
    } 
} 

updateDataFromUrl方法中包含了大量的代碼(攤位,前後processData電話),我想在多個處理器重用,爲此我把代碼放到一個抽象類。

的問題是:我想訪問其新添加的updateData方法(這裏yearmonthday)提供的數據。當呼叫流經不知道這些參數的抽象類時,這些信息就會丟失。我如何修改這個架構來保存這些信息?

以下解決方案來到我的腦海裏,都用明顯的缺點:

  1. 提供URL中的抽象方法,並從那裏再次提取參數。
  2. 斯普利特updateDataFromUrl方法分爲兩個兩個方法(在processData呼叫,事後部分之前的部分):(什麼問題也有,我只需要在procecssData方法和從未在URL參數?)。現在直接在ConcreteProcessor中使用這些方法。 (問題:updateDataFromUrl方法有很多方面,我需要兩者的前後processData電話後我怎樣才能得到這個數據的新創建方法之間轉移。?)
+1

「狀態」對象如何? 'public abstract String processData(String data,Object state);'你可以創建任何狀態並且你的抽象類只是轉發它,你的具體實現將知道它是什麼... – Fildor

+0

@Fildor我想過同樣的,但是不是這種方法有點怪異嗎?我不確定這個...... – theomega

+0

那麼,至少這是對代碼的最小改動,因爲它現在就是這樣。儘管與ewernli的第二種方法相比,這是一件非常有趣的事情。 – Fildor

回答

1

只有很小的修改導致這種解決方案(如果我沒有錯過某一點(未經測試))。

會得到以下好處:

  • 信息傳遞是非常簡單(使用實例變量)
  • 您從外部(公有)查看保留線程安全
  • ConcreteProcessor可以保持不變

可能最好不要從updateData返回ConcreteProcessor,但一些不可變類型代表轉換的數據。

public abstract class AbstractProcessor { 
    public void updateDataFromUrl(String url) { 
     //Download url 
     //Decrypt, and do a lot of stuff, 
     String data = "abc"; //Result from downloading 

     String processed = processData(data); 

     //Do a lot of other things with the transformed data 
    } 

    public abstract String processData(String data); 
} 


final class ConcreteProcessor extends AbstractProcessor { 
    public static ConcreteProcessor updateData(int year, int month, int day) { 
      ConcreteProcessor p = new ConcreteProcessor(year, month, day); 
      p.updateDataFromUrl(url); 
      return p; 
    } 

    private /* instance vars for year, month, day, url, ... */ 

    private ConcreteProcessor(int year, int month, int day) { 
      this.year = year; 
      this.month = month; 
      this.day = day; 
      this.url = String.format("http://%d.%d.%d", year, month, day); 
    } 


    @Override 
    public String processData(String data) { 
     //Process the data 

     //--------------- 
     // NO PROBLEM: 
     //---------------- 
     //Easy to access to year, month, day using the instance vars 

     return null; 
    } 
} 

但整體概念看起來像一個線性管道,因此它可能是最好的使管道更清晰。你需要一些承載的國家,但這不應該是使用我所認爲的泛型的一個大問題。

2

兩個想法:

  1. ConcreteProcessor中使用實例變量來存儲年,月,日。這兩種方法都可以訪問對象的實例變量。儘管如此,抽象類不能訪問它們。注意:對象不再是線程安全的。您必須有多個獨立的處理器才能同時處理數據。

  2. 顛倒依賴和使用組合。通用類Processor包含通用邏輯。當您調用updateDataFromUrl時,還會傳遞一個實現processData(確實是一種回調)的ProcessingStrategy的實例。

可能有幾個想法的變化。

+0

我會提出類似的建議,但有一個解釋:重新設計使用「處理器」的每個請求實例,或者使用「處理器」作爲這種每個請求對象的工廠。遵循Java'Pattern'和'Matcher'的例子。 –

+0

嗯,我真的想出了第一個想法,但我不想破壞線程安全。你可以用第二個答案進一步瞭解更多細節嗎?我不完全明白這一點。不管怎麼說,還是要謝謝你! – theomega

+0

@theomega如果你按照我的評論設計,這可以避免任何多線程問題。 –

相關問題