Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 把自己编入一个角落_Java_Design Patterns_Oop - Fatal编程技术网

Java 把自己编入一个角落

Java 把自己编入一个角落,java,design-patterns,oop,Java,Design Patterns,Oop,我们有一组类,这些类派生自一组公共接口 IFoo-> BasicFoo, ReverseFoo, ForwardFoo IBar -> UpBar, DownBar, SidewaysBar IYelp -> Yip, Yap, Yup 其中,Foo的构造器看起来像Foo(IBar,IYelp)这些项目在整个项目中使用 存在另一个类,该类有一个签名为public double CalcSomething(IFoo,IAnotherClass)的方法,该方法在某个点应用于每个F

我们有一组类,这些类派生自一组公共接口

IFoo-> BasicFoo, ReverseFoo, ForwardFoo
IBar -> UpBar, DownBar, SidewaysBar
IYelp -> Yip, Yap, Yup
其中,Foo的构造器看起来像
Foo(IBar,IYelp)
这些项目在整个项目中使用

存在另一个类,该类有一个签名为
public double CalcSomething(IFoo,IAnotherClass)
的方法,该方法在某个点应用于每个Foo。我们收到一个来自上面的请求,一个特定的对象组合,比如说一个
BasicFoo(UpBar,Yip)
,使用一个不同于
CalcSomething
中的算法

我的第一个直觉是,让我们更改IFoo接口,这样我们就可以将逻辑向下移动到Foo类级别,将构造函数更改为
Foo(IBar、IYelp、IStrategy)
,然后让Foo对象封装这个逻辑。不幸的是,我们还被告知,体系结构的设计规定,
IFoo
、它的实现和
IAnotherClass
之间没有依赖关系。他们对此态度坚决

好的,当然,然后我想我可能会使用访客模式,但是。。。怎样?进行组合的全部目的是使其他类看不到实现细节。反射以查看对象内部,完全破坏封装?哦,他妈的不

所以我来这里是因为我不知所措。有人对我们如何在不修改组成或破坏封装的情况下处理其中一个组成的特殊情况有什么建议吗?一定有一个简单的解决方案,我正在寻找

编辑:

删除了令人不快的开头。
将“特殊处理”更改为更具描述性的含义。

一个基于您提供的
IFoo
类型选择适当算法的
计算工厂将解决问题(以条件为代价):


calcSomething无法避免获得执行“特殊”行为所需的知识,但除此之外,您可以通过这种方式维护大部分封装

为扩展IFoo的特殊处理创建标记接口IQualifyForSpecialTreatment。将BasicFoo扩展到SpecialBasicFoo,并让它实现IQualifyForSpecialTreatment


    interface IQualifyForSpecialTreatment extends IFoo {
    }
    class SpecialBasicFoo extends BasicFoo implements IQualifyForSpecialTreatment {
        ...
    }
然后,您可以添加另一种calcSomething:


    calcSomething (IQualifyForSpecialTreatment foo, IAnotherClass whatever) {
        ... perform "special" variant of calculation
    }
    calcSomething (IFoo foo, IAnotherClass whatever) {
        ... perform "normal" variant of calculation
    }

本着KISS的精神,我将在IFoo中添加一个方法isSpecial(),并使用它来决定在CalcSomething()中使用哪个算法


这假设这是唯一的特例。

当您在规范中有一个缺点时,您很可能在实现中有一个缺点。我看不出有什么方法可以非常清晰地做到这一点。我不明白的主要问题是——在继承
IFoo
的类中封装特殊逻辑如何创建对
IAnotherClass
的依赖关系?好吧,delfuego,如果我将其移动到Foo,该方法必须具有签名IFoo::CalcSomething(IAnotherClass).我们只是在讨论这是否能实现我们的目标。我们看不到任何其他方法可以通过使用反射来深入了解如何分割事物。虽然耦合更紧密,但您可以从为客户端提供调用
calcSomething()
:+1的上下文的角度来看待这一点,如果这是一次性事件,我建议的工厂方法可能比它需要的更重。简单、整洁、充足。如果违反了“唯一特殊情况”假设,则可以重构isSpecial()以返回“要应用的计算算法”值。

    calcSomething (IQualifyForSpecialTreatment foo, IAnotherClass whatever) {
        ... perform "special" variant of calculation
    }
    calcSomething (IFoo foo, IAnotherClass whatever) {
        ... perform "normal" variant of calculation
    }