开发者

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

I am trying to incorporate more functional programming idioms into my java development. One pattern that I like the most and avoids side effects is building classes that have behavior but they don't necessarily have any state. The behavior is locked into the methods but they only act on the parameters passed in.

The code below is code I am trying to avoid:

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();
    }

}

The code below is nothing special but I am acting on the parameters and state is contained within that class. We still may run into issues with this class but that is an issue with the method and the state of the data, we can address issues in the routine as opposed to not trusting the entire object.

Is this some form of idiom? Is this similar to any pattern that you use?

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 //

Issues with the code above:

  1. I wanted to declare the Data class private, but then I can't really reference it outside of the class:

  2. I can't override the SemiStateful class and access the private members.

Usage:

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

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

Edit-1: This is a good comment. My response: "As soon as you make the Data class accessible outside the main class you are exposing implementation details, " -- comment.

My Response: The Data class is a simple POJO and will work like other pojos with setters and getters. What I was doing in the class above was trying to only manipulate the Data class from the behavior class, SemiStatefulOOP. I do intend to have stateless classes but I wanted to have a clear separation from the state classes and the behavior classes.

Related:

Stateless Desi开发者_Go百科gn Pattern http://guides.brucejmack.biz/Pattern%20Documents/Stateless%20Design%20Pattern.htm


There's an interesting OO architectural style that aims to separate the data and the behavior of a system, so that they can evolve independently: the DCI Architecture.

In practice, you create data objects for your domain concepts (possibly only with simple behavior related to the data itself); and behavior objects that work with the data objects and that realize the use cases of the system. These behavior objects are seen as roles that the domain objects can play, and are materialized with the OO concept of a trait (pdf).

Scala has traits, but Java doesn't. You can try to use the Qi4J framework in Java for that.


One of the key points of OO programming is that you hide implementation details. Your approach doesn't seem to be doing that - as soon as you make the Data class accessible outside the main class you are exposing implemntation details, and effectively exposing data representation.

It is of course impossible to make all classes stateless - something has to hold the state, and it's not clear to me why holding it in Data is preferable to holding it in the main class.

Finally a principle of OO programming is to keep data and functionality related to it in the same place, i.e. the same class. In short, while your proposal is interesting, I think the problems it creates are worse than the problems it solves.


building classes that have behavior but they don't necessarily have any state

See wiki

The strategy pattern is intended to provide a means to define a family of algorithms, encapsulate each one as an object, and make them interchangeable. The strategy pattern lets the algorithms vary independently from clients that use them.

// 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
    }
}


I'm not sure I understand quite what you're asking here. As an alternative to BadObject's statefulness, could you not simply declare the method as

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

or similar?

In general, when I think of functional and/or stateless idioms, the overwhelming code pattern that crops up is to have methods take parameters for everything they depend on (instead of getting them from fields or static methods or train wrecks (getFoo().getCustomer().getAddress().getHouseName())). That and return the result, rather than modifying the state of other objects.

At this point, all the data classes can be immutable since there's nothing to modify, which makes the code much easier to understand and reason about.

This wouldn't be one of the original GoF patterns, but I believe Josh Bloch has a paragraph on this in Effective Java entitled something like "Prefer immutability", which is catchy enough.


I think that the best solution to incorporate more functional programming into your projects is to use a functional programming language, like Scala. Scala is fully interoperable with Java and compatible with JVM. Scala classes is Java classes and vise versa. Why not to try it... :)

Java is full OOP language and my opinion is that functional paradigms just doesn`t fit nicely into it.


It looks like you have utility classes.

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();
    }
}

You don't need to create an object.

Data.execute();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜