有一个有状态的助手类是不好的做法吗?

时间:2016-12-15 19:05:48

标签: java design-patterns

我有一个特例,如下图所示。 我有一个Listener类和一个Uploader类。侦听器类通过网络侦听消息,处理它们并从中创建另一个小对象。

public class Listener {
    Uploader uploader;

    Listener(String location) {
        uploader = new Uploader(location);
    }

public void listen(Message msg) {
    ProcessedObject obj = process(msg);
    uploader.add(obj);
}

public void terminate() {
    if (null != uploader) {
        uploader.finish();
    }
}

}

Uploader类通过add方法获取一个对象,并决定何时上传。为此,它维护一个列表。它还具有位置字符串,该字符串特定于一个侦听器。这是要点:

/**
 * This class is not thread safe, and an object should not be shared across threads
 *
*/
public class Uploader {
    String location;
    List<ProcessedObject> objects;

    Uploader(String location) {
        this.location = location;
    }

    void add(ProcessedObject obj) {
        objects.add(obj);

        if (objects.size() > PARTITION_SIZE) {
            uploadObjects(objects);
            objects.clear();
        }
    }

    void finish() {
        uploadObjects(objects);
    }
}

因此,如果对象数大于PARTITION_SIZE,则上传。应用程序中有多个侦听器,每个侦听器都在一个单独的线程上运行。每个监听器都有自己的上传器对象。我已经清楚地提到过这个类在javadoc中不是线程安全的。

现在我的问题是,这是一个好习惯吗?

我的一些同事说这不是一个好习惯,建议使用静态方法上传,而不是创建上传者的实例。但我的论点是,这将使我的监听器类变得混乱(因为那时监听器必须保持计数,并在终止剩余对象之前再次检查并上传)

通过我的方法,整个分区和上传逻辑在上传器类中可用,因此它提高了可读性和可维护性。

我的问题是,我的方法是不好的做法(考虑到我特别指出上传者并不意味着线程安全)?

此外,我在这里尝试做什么设计模式?如果是,哪一个?

编辑:我接受我没有正确构建问题。我不关心分区或上传。关于为每个线程创建一个Uploader类对象的方法,与使用静态方法创建无状态Uploader类来完成这项工作。

我是否上传剩余的对象,或者我是否应该进行分区,不是这个问题的关注点。

2 个答案:

答案 0 :(得分:0)

您可以使用私有静态ThreadLocal来合并这两种方法来保存上传器。

从更大的角度看:

我认为你的同事有一个有效的观点。考虑到Uploader可以位于单独的线程或线程池中。这些都可以从Listener中抽象出来并隐藏起来。然后上传者可以根据元素的数量决定它是否有足够的工作,或者它是否已经设置了毫秒的持续时间而没有接收到更多的元素。也许允许倾听者冲洗/完成,但它不应该 - 那种要求对其他程序员来说是一个难题。

答案 1 :(得分:0)

我认为你以错误的方式提出这个问题。你问这是不是一种坏习惯。

反过来思考。你正在解决的任务是什么?这项任务有意义吗?你的实施是否很好?

您正在解决的任务是&#34;包装&#34;一些对象一起上传,而不是逐个上传。

减少上传次数可能完全有意义。但也许不是,这取决于单个上传成本的开销。不知道我的假设是它可能完全有意义。

现在,您的实施是否良好?嗯......

首先,您提到了多个线程,因此您需要特别注意在对象列表上进行同步。

接下来,等待PARTITION_SIZE是否合适?如果你只有PARTITION_SIZE - 1个对象怎么办?你可以永远等待最后一个,而不是发送其他对象。

最后,如果您的应用程序出现故障会怎样?您将丢失已发布到上传队列但尚未发送的数据。这可能真的很糟糕。这个解决方案不可靠。