簡體   English   中英

Java-這是一個成語或模式,無狀態的行為類

[英]Java - is this an idiom or pattern, behavior classes with no state

我正在嘗試將更多功能性編程習慣用法納入我的Java開發中。 我最喜歡並避免副作用的一種模式是構建具有行為的類,但它們不一定具有任何狀態。 該行為被鎖定在方法中,但它們僅對傳入的參數起作用。

下面的代碼是我要避免的代碼:

public class BadObject {

    private Map<String, String> data = new HashMap<String, String>();

    public BadObject() {
        data.put("data", "data");
    }

    /**
     * Act on the data class. But this is bad because we can't
     * rely on the integrity of the object's state.     
     */
    public void execute() {
        data.get("data").toString();
    }

}

下面的代碼沒什么特別的,但是我作用於參數,並且狀態包含在該類中。 我們仍然可能遇到此類問題,但這是方法和數據狀態的問題,我們可以解決例程中的問題,而不是不信任整個對象。

這是某種成語嗎? 這類似於您使用的任何模式嗎?

public class SemiStatefulOOP {

    /**
     * Private class implies that I can access the members of the <code>Data</code> class
     * within the <code>SemiStatefulOOP</code> class and I can also access
     * the getData method from some other class.
     *  
     * @see Test1
     *
     */
    class Data {
        private int counter = 0;        
        public int getData() {
            return counter;
        }
        public String toString() { return Integer.toString(counter); }
    }

    /**
     * Act on the data class. 
     */
    public void execute(final Data data) {
        data.counter++;        
    }

    /**
     * Act on the data class. 
     */
    public void updateStateWithCallToService(final Data data) {
        data.counter++;       
    }

    /**
     * Similar to CLOS (Common Lisp Object System) make instance.
     */
    public Data makeInstance() {
        return new Data();
    }

} // End of Class //

上面的代碼有問題:

  1. 我想將Data類聲明為私有,但實際上我不能在類外部引用它:

  2. 我無法重寫SemiStateful類並訪問私有成員。

用法:

final SemiStatefulOOP someObject = new SemiStatefulOOP();
final SemiStatefulOOP.Data data = someObject.makeInstance(); 

someObject.execute(data);
someObject.updateStateWithCallToService(data);

編輯1:這是一個很好的評論。 我的回答是:“一旦使Data類可以在主類之外訪問,就將公開實現細節,”-評論。

我的回應:Data類是一個簡單的POJO,它將像其他帶有setter和getter的pojo一樣工作。 我在上面的類中所做的只是嘗試操作行為類SemiStatefulOOP中的Data類。 我確實打算有無狀態類,但我想與狀態類和行為類有明顯的區別。

有關:

無狀態設計模式http://guides.brucejmack.biz/Pattern%20Documents/Stateless%20Design%20Pattern.htm

OO編程的關鍵點之一是隱藏實現細節。 您的方法似乎並沒有做到這一點-一旦使Data類在主類之外可以訪問,您就可以公開實現細節,並有效地公開數據表示形式。

當然,使所有類都變為無狀態是不可能的-某種東西必須保持狀態,而且我不清楚為什么在Data中持有它比在主類中持有更可取。

最后,OO編程的原理是將與其相關的數據和功能保持在同一位置,即同一類。 簡而言之,盡管您的建議很有趣,但我認為它提出的問題比解決的問題更糟。

有一種有趣的OO架構風格,旨在將數據和系統行為分開,以便它們可以獨立發展: DCI架構

實際上,您將為您的域概念創建數據對象(可能僅具有與數據本身相關的簡單行為); 行為對象與數據對象一起工作,並實現系統的用例。 這些行為對象被視為領域對象可以扮演的角色,並通過OO 特性的特性 (pdf)得以實現。

Scala具有特征,而Java沒有。 您可以嘗試為此使用Java中的Qi4J框架

建立具有行為但不一定具有任何狀態的類

參見維基

策略模式旨在提供一種定義一系列算法的方法,將每個算法封裝為一個對象,並使它們可互換。 策略模式使算法可以獨立於使用它們的客戶端而變化。

// The context class uses this to call the concrete strategy
interface Strategy {
    int execute(int a, int b); 
}

// Implements the algorithm using the strategy interface
class ConcreteStrategyAdd implements Strategy {

    public int execute(int a, int b) {
        System.out.println("Called ConcreteStrategyAdd's execute()");
        return a + b;  // Do an addition with a and b
    }
}

我不確定我是否完全理解您的要求。 作為BadObject的有狀態性的替代方法,您能否不能簡單地將方法聲明為

public void execute(Map<String, String> data) {
    ...
}

或類似的?

總的來說,當我想到功能和/或無狀態習語時,出現的壓倒性代碼模式是讓方法為它們依賴的所有內容獲取參數(而不是從字段或靜態方法中獲取參數或訓練殘骸( getFoo().getCustomer().getAddress().getHouseName() ))。 那並返回結果,而不是修改其他對象的狀態。

此時,所有數據類都是不可變的,因為無需進行任何修改,這使得代碼更易於理解和推理。

這不是原始的GoF模式之一,但是我相信Josh Bloch在Effective Java中對此有一段標題,例如“首選不變性”,這很容易上手。

我認為,將更多功能性編程集成到您的項目中的最佳解決方案是使用功能性編程語言,例如Scala。 Scala可與Java完全互操作,並與JVM兼容。 Scala類是Java類,反之亦然。 為什么不嘗試一下... :)

Java是完整的OOP語言,我的觀點是功能范式不太適合它。

看來您有實用程序類。

public class Data {    
    private static final Map<String, String> data = new HashMap<String, String>();
    static {
        data.put("data", "data");
    }
    private Data() { }

    /**
     * Act on the data class.     
     */
    public static void execute() {
        data.get("data").toString();
    }
}

您無需創建對象。

Data.execute();

暫無
暫無

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

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