首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >条件命令模式

条件命令模式
EN

Software Engineering用户
提问于 2020-07-03 16:12:31
回答 1查看 580关注 0票数 -2

我有一个抽象定义了类似于指挥模式的东西,

代码语言:javascript
复制
interface Participant {
    void proceed();
}

Participants被分组在一个集合中,并被调用在一起。但由于一定的条件,小组中的每一位参与者都不必参加特定的电话会议。

我想在我的抽象中添加一种允许的方法。这样做的想法是,调用方可以在调用Participant之前询问是否应该调用它。

Is --这是正确的方法吗?也许确定补贴的条件可能需要非常昂贵的计算,以后需要在proceed()中再次执行。如果实现必须是无状态的,则无法保存两个调用之间的计算,并且性能将受到影响。

顺便说一句,如果这是一个可以接受的方法,我需要一个明确的名称,为津贴职能。我想到了canProceed(),但我想避免重复这个动作的名称,一个简单的can()对我来说似乎很模糊。这类函数是否有通常的命名约定?

EN

回答 1

Software Engineering用户

回答已采纳

发布于 2020-07-04 20:23:20

问题

让我们来看一下与指挥模式的类比:

  • Client创建实现Participant的类的对象(类似于Command)。为了方便起见,让我们调用其中一个类ConcreteParticipant
  • ConcreteParticipant对象知道所有上下文,例如执行其职责的receiverproceed() (类似于命令模式中的execute() )。此上下文可以在构造时或以后提供,但在任何调用之前提供。
  • invoker对象稍微复杂一些,因为它有一个Participant集合,例如,ConcreteParticipant具有执行条件和proceed()计算所需的所有上下文(例如,命令模式中的receiver )。
  • 说明Participant是否必须proceed()的条件不是由invoker计算的,而是由Participant本身计算的。

您的初始方法

第一种方法是公开参与者条件确定,并让调用方进行过滤:

代码语言:javascript
复制
//PSEUDO CODE:  I'm not Java fluent...

interface Participant {
    void proceed();
    boolean isApplicable();  // but why?
}

// in the invoker:  

for (Participant p: participants) {
    if (p.isApplicable()) 
       p.proceed();
}

这样做有什么好处呢?如果Participant自己确定条件是否适用(甚至有些条件是无条件的),那么让另一个类退出是没有意义的。

,保持简单!

根据知识最少原则和tell 分离关注点,除非有忘记告诉您的原因,否则不应该公开这种情况。

相反,您应该相信参与者只有在必要时才能工作:

代码语言:javascript
复制
interface Participant {
    void proceed();
}
class ConcreteParticipant implements Participant {
    private bolean isApplicable() { ... }  // no longer explosed in the interface
    public void proceed() { 
        if (isApplicable()) {
            ...
        }
    }
}  
class ConcreteUnconditionalParticipant implements Participant {
    public void proceed() { 
        doItAnyway(); 
    }
}  

使用这种方法,您不再会出现任何性能问题,即重做两次相同的时间操作:您可以重构代码而不更改接口:

代码语言:javascript
复制
class OtherConcreteParticipant implements Participant {
    private ComplexResult prepareCondition() { ...} 
    private bolean isApplicable (ComplexResult r) { ... }  // stateless :-) 
    public void proceed() { 
        ComplexResult r = prepareCondition(); 
        if (isApplicable(r)) {
            ... // here you may reuse r.  
        }
    }
}  

而且您也不再存在命名问题;-)

需要更严格的控制?

如果调用方必须做一些记账工作,例如,计算参与方的数目,您可以稍微更改您的界面:

代码语言:javascript
复制
interface TalkativeParticipant {
    boolean proceed();  // return true if it was active, and false if not applicable.
}

请注意,这种方法还将使您能够更详细地决定如何调用参与者:

  • 在第一个参与者完成工作后,您可以轻松地停止通话。
  • 或者在第一个不起作用的电话之后停止。

备注:第一个结果也可以使用责任链模式实现。但责任链要求每个Participant都知道自己的继任者。THis与您所描述的情况非常不同。参与者的集合似乎更容易管理。

票数 3
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/412321

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档