Java - 这是一个习语或模式吗,没有状态的行为类

发布于 2024-10-12 01:27:48 字数 2469 浏览 6 评论 0原文

我正在尝试将更多的函数式编程习惯融入到我的 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);

Edit-1:这是一个很好的评论。我的回答是:“一旦你让 Data 类在主类之外可访问,你就暴露了实现细节,”——评论。

我的回应:Data 类是一个简单的 POJO,并且将像其他带有 setter 和 getter 的 pojo 一样工作。我在上面的类中所做的只是尝试仅操作行为类 SemiStatefulOOP 中的 Data 类。我确实打算拥有无状态类,但我希望将状态类和行为类明确分开。

相关:

无状态设计模式 http://guides.brucejmack.biz/Pattern%20Documents/Stateless%20Design %20Pattern.htm

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 Design Pattern
http://guides.brucejmack.biz/Pattern%20Documents/Stateless%20Design%20Pattern.htm

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

硪扪都還晓 2024-10-19 01:27:48

有一种有趣的 OO 架构风格,旨在将系统的数据和行为分开,以便它们可以独立发展: DCI 架构

在实践中,您为领域概念创建数据对象(可能仅具有与数据本身相关的简单行为);行为对象与数据对象一起工作并实现系统的用例。这些行为对象被视为领域对象可以扮演的角色,并通过 特质(pdf)

Scala 有特征,但 Java 没有。您可以尝试使用 Java 中的 Qi4J 框架 来实现此目的。

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.

夜巴黎 2024-10-19 01:27:48

OO 编程的关键点之一是隐藏实现细节。您的方法似乎并没有这样做 - 一旦您使 Data 类可在主类之外访问,您就公开了实现细节,并有效地公开了数据表示。

当然不可能使所有类都无状态 - 必须有某种东西来保存状态,而且我不清楚为什么将其保存在 Data 中比将其保存在主类中更好。

最后,面向对象编程的一个原则是将与其相关的数据和功能放在同一个地方,即同一个类。简而言之,虽然你的建议很有趣,但我认为它造成的问题比它解决的问题更糟糕。

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.

浅忆 2024-10-19 01:27:48

构建具有行为的类
但他们不一定有任何
状态

请参阅wiki

策略模式旨在提供一种定义策略模式的方法一系列算法,将每个算法封装为一个对象,并使它们可以互换。策略模式使算法能够独立于使用它们的客户端而变化。

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

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
    }
}
鹊巢 2024-10-19 01:27:48

我不确定我是否完全理解你在这里问的问题。作为 BadObject 状态性的替代方案,您是否可以简单地将方法声明为

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

或类似的方法?

一般来说,当我想到函数式和/或无状态惯用语时,出现的压倒性代码模式是让方法为它们所依赖的所有内容获取参数(而不是从字段或静态方法或火车残骸中获取它们(getFoo ().getCustomer().getAddress().getHouseName()))。并且返回结果,而不是修改其他对象的状态。

此时,所有数据类都可以是不可变的,因为无需修改任何内容,这使得代码更容易理解和推理。

这不会是最初的 GoF 模式之一,但我相信 Josh Bloch 在 Effective Java 中对此有一个段落,标题为“更喜欢不变性”,这足够吸引人了。

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.

娇女薄笑 2024-10-19 01:27:48

我认为将更多函数式编程融入到项目中的最佳解决方案是使用函数式编程语言,例如 Scala。 Scala 与 Java 完全可互操作并与 JVM 兼容。 Scala 类是 Java 类,反之亦然。为什么不尝试一下...:)

Java 是完全的 OOP 语言,我的观点是函数式范例不太适合它。

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.

请恋爱 2024-10-19 01:27:48

看来您有实用程序类。

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

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文