接口地狱或可接受的设计?

时间:2012-08-22 20:08:44

标签: design-patterns interface strategy-pattern

我正在重构一些遗留代码,这些代码通过case语句一遍又一遍地做同样的事情:

switch(identifier)
    case firstIdentifier: 
        (SomeCast).SetProperties(Prop1,Prop2,Prop3);
        break;
    ...
    case anotherIdentifier:
        (SomeDifferentCast).SetProperties(Prop1, Prop2, Prop3);
        break;

所以,我尝试创建一个独特的界面,以便这可以成为

(SameInterfaceCast).SetProperties(Prop1,Prop2,Prop3);

然而,我发现有些项目甚至没有使用所有属性。所以,我开始想到更像这样的事情:

if(item is InterfaceForProp1)
    (InterfaceForProp1).SetProp1(Prop1);
if(item is InterfaceForProp2)
    (InterfaceForProp2).SetProp2(Prop2);
if(item is InterfaceForProp3)
    (InterfaceForProp3).SetProp3(Prop3);

你可以创建一个这样的类:

public class MyClassUsesProp2And3 : InterfaceForProp2, InterfaceForProp3

但是,我担心我过度破坏了这段代码,而且它可能会过多。也许我不应该太害怕什么本质上是一个方法接口,但我想看看我是否缺少一个设计模式在走这条路径之前? (唯一出现在我脑海中但不太合适的是DecoratorComposite模式)

更新

所有属性都是唯一类型。

最终,这是依赖注入的一种形式。代码太乱了,现在使用像Ninject这样的东西,但最终我甚至可以摆脱其中一些并使用注射容器。除了设置变量之外,目前还有一些逻辑正在完成。这是所有遗留代码,我只想一点一点地清理它。

4 个答案:

答案 0 :(得分:1)

我不知道这是否有“正确”的答案,但这就是我要做的。

class Properties {
    prop1
    prop2
    prop3
}

interface PropertySetable {
     setProperties(Properties prop);
}
public class MyClassUsesProp2And3 implements PropertySetable {
    setProperties(Properties prop) {
       //I know I need only 2 and 3
       myProp2 = prop.prop2;
       myProp3 = prop.prop3;
    }

}

在调用函数时,你不应该有一个强制转换。

 someFunc(..., PropertySetable, Properties,...) {
      PropertySetable.setProperties(Properties); 
 } 

这是基本结构。

您应该封装属性 - 将属性设为私有并具有相关的构造函数。或者使用Builder模式构建属性......以及更多......

答案 1 :(得分:1)

我认为答案取决于你想要首先重构代码的原因。

  • 如果你想完全摆脱开关块,那么你将不得不用一个带三个参数的方法实现一个接口。每个类都必须弄清楚哪些参数适用以及如何处理这些参数。
  • 如果您想减少代码的总量,那么我不确定添加特定于类的属性设置逻辑是否比原始switch语句少了代码
  • 如果您想利用编辑器的代码完成功能来插入具有正确数量的属性/ args的正确方法,那么只需在每个类上实现正确的方法并完全避免使用该接口

答案 2 :(得分:1)

当您遇到switch语句和类型转换时,visitor pattern是标准解决方案。每个案例的代码将在访问者类中进入单独的方法。并且您的每个类都将只实现一个接口 - accept方法来接受访问者。你将获得比现在更多的代码,但它会读得更清晰。

答案 3 :(得分:1)

基本上你想让actor(使用setProp方法输入)使用相同类型的'Actor'并使属性(prop1 ... n)成为同一类型'Prop'。这会将您的代码减少到

actor.setProp(prop)

如果你想避免使用instanceOf,我唯一能想到的方法是使用访问者模式,让'Prop'成为访问者。我也会使用模板方法让我的生活更轻松。在Java中,我会使它看起来像这样(对于两种实际的Prop)。

class Actor {

    protected void set(Prop1 p1) {
        // Template method, do nothing
    }

    protected void set(Prop2 p2) {
        // Template method, do nothing
    }

    public void setProp(Prop p) {
        p.visit(this);
    }

    public interface Prop {
        void visit(Actor a);
    }

    public static Prop makeComposite(final Prop...props ) {
        return new Prop() {

            @Override
            public void visit(final Actor a) {
                for (final Prop p : props) {
                    p.visit(a);
                }
            }
        };
    }

    public static class Prop1 implements Prop {
        public void visit(Actor a) {
            a.set(this);
        }
    }

    public static class Prop2 implements Prop {
        public void visit(Actor a) {
            a.set(this);
        }
    }
}

这允许你做这样的事情:

    ConcreteActor a = new ConcreteActor();
    Prop p = Actor.makeComposite(new ConcreteProp1(42), new ConcreteProp2(-5));
    a.setProp(p);

......这太棒了!