系统领域对象设计,希望大家探讨

本人在做邮件消息发送程序,目前可以按2种方式发送消息,
1.internet email
2.站内消息

于是定义了一个Message接口,以及EmailMessage和站内消息(StationMessage)的实现类。

又有2种生成message的方式:键盘敲进去和选择模板
于是又定义了一个MessageRender接口
和 键盘输入(SimpleMessageRenderImpl),模板邮件输入(TemplateMessageRenderImpl)2个实现类

然后又定义了一个MessageSender接口和 MailMessageSenderImpl, StationMessageSenderImpl 2个发送
消息的实现类

按照开-闭原则,这个设计是合理的。
有2个疑问:1.MailMessageSenderImpl不可能发送StationMessage,同样StationMessageSenderImpl 不可能
发送EmailMessage, 因此这种是不是属于过渡设计??到底有没有必要把站内消息发送和email消息发送写在同一个模块里??

2.关于MessageRender, SimpleMessageRenderImpl或者StationMessageSenderImpl至少返回一个Message的具体实现类

方式1:
interface MessageRender {
Message getEmailMessage();
Message getStationMessage();
} 然后SimpleMessageRenderImpl,TemplateMessageRenderImpl 分别实现

方式2:
interface MessageRender {
Message getMessage();
}
需要4个实现类SimpleEmailMessageRenderImpl,SimpleStationMessageRenderImpl,
TemplateMailMessageSenderImpl,TemplateStationMessageRenderImpl.

方式一缺点:当再来一种其他Message实现的话,又得在MessageRender里面加一个方法Message getOtherMessage();
然后分别在各实现类里面编写,修改的太多了

方式二缺点:类太多

希望大侠解惑

关于MessageRender的方式1肯定是错误的,这样的话就不用接口了。

>到底有没有必要把站内消息发送和email消息发送写在同一个模块里
你潜意识里觉得是有必要的,我因为不是很了解需求,确实没有看到他们有统一的必要性,尽管他们都有一个message消息概念在里面。

其实这还是和我们的数学思维有关,潜意识里看到相同的就想合并同类项,就想使用一个精简的公式统一代表他们,喜欢先总结,而不是首先分析拆解。

我的建议,首先分开处理,然后,两个功能完成后,我们再重构,进行合并,而不要一开始就去合并,就产生过度设计,离开需求很远。

回freebox: 你的意思是按方式一没必要用message接口了?

回BANQ: 确实如你所说的这样, 我也怀疑将它们合在一起!

需求是这样的,用户可以选择(单选框)使用 email 发送, 或者站内消息发送, 另外系统后台也需要发送邮件功能

方式1我认为没必要用MessageRender接口了,在方式一里它的任务是什么呢?当加进一个getXXMessage()功能时,已有的实现类怎么办?实现一个空方法么?那干嘛不直接在这方法里把功能实现了,而非要另做一个XXMessageImpl类呢?

按我的识别,这应该是个抽象工厂。

回freebox

MessageRender 接口主要2种实现, 一种是手写输入(SimpleMessageRenderImpl), 一种是velocity模板实现(TemplateMessageRenderImpl), 这个接口跟消息类型(邮件消息,站内消息)无关.

按照方式一的话 MessageRender 本身就是抽象工厂, 而有2种工厂实现, 缺点就跟你指出的一样

首先我不明白StationMessage是什么,是一个行为还是一个消息呢?如果它是个消息,就是说在它被创建的时候就决定了它是站内消息,但是我觉得事实好像不是这样,应该是由输入或模板创建一个消息,直到发送它的时候才确定是发到站内还是发到email。


interface Sender{
public void send(Message message);
}
class StationSender implements Sender{//我不用理会消息是怎么生成的,反正我只把它发到站内}
interface Message{
}
class TemplateMessage implements Message{
//我会生成一个模板消息}

to freebox :

你理解错误我的意思了, StationMessage是一种Message, 而没有那种TemplateMessage, 而是TemplateMessageRender 它是一种从模板生成Message的方式.

呵呵,freeBox说的是如何发送,而kogle讲的是如何产生message,把两个人的结合起来问题就解决了呵呵。^_^

我觉得如果消息的种类不会发生变化的话,就采用第一种抽象工厂的方式。如果消息的种类以后要发生变化那么就采用第二种方式,这样更符合开闭原则。具体还是根据需求决定。

我没搞懂StationMessage到底是什么意义,因为我不了解需求,我的理解是它就是一个Message,只不过只在站内发送,但是愿意的话也可以发到email。