如何实现对两个相同类的一个引用?

时间:2012-07-25 17:48:47

标签: java design-patterns

我有两个具有相同实现但名称不同的类。它们已生成,我无法修改它们:

public class Foo {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public class Bar {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

我需要用数据填充这些类,因为它们相同,所以更喜欢使用单个类或引用,然后根据需要转换为(或希望解决方案更优雅)Foo或Bar。从概念上讲:

FooOrBar fob = ????;   
fob.setName("XYZ");

Foo f = fob.(???);
Bar b = fob.(???);

我已经研究过泛型,但似乎是因为当你真的不知道你将要操作什么类时。我可以使用某种类型的类或参考来实现这一目标吗?

7月26日编辑:

道歉,如果这样的后续行动不好,我可以发布新的,如果需要的话。我正在实施Tomasz的适配器模式,但我的最后一步与他的不同。我需要对接口对象进行条件赋值。以下是我所拥有的,到目前为止我没有得到任何错误或警告,但我想知道这是不是出于某种原因这是不好的做法?也许我应该使用反射或泛型来确定接口的类?这将是一种方法,只有我的代码会调用,我会知道条件。我已经搜索了条件接口分配但没有找到太多。

FooOrBar fob;  //interface

if (condition true) {

    fob = new FooAdapter();  //FooAdapter implements FooOrBar
} else {
    fob = new BarAdapter();  //BarAdapter implements FooOrBar
}

fob.setName("XYZ");

4 个答案:

答案 0 :(得分:2)

您正在寻找的内容称为,Java不支持。尝试动态语言,例如

在Java中,假设您无法修改FooBar,则需要 Adapter 模式。首先在FooBar上创建一个抽象:

public interface FooOrBar {
    String getName();
    void setName(String name);
}

并且有两个这样的适配器(BarAdapter几乎相同):

public class FooAdapter implements FooOrBar {

    private final Foo foo;

    public FooAdapter(Foo foo) {
        this.foo = foo;
    }

    public String getName() {
        return foo.getName();
    }

    public void setName(String name) {
        foo.setName(name);
    }

}

现在你可以说:

FooOrBar fob = new FooAdapter(foo);
FooOrBar fob2 = new BarAdapter(bar);

fob.setName("XYZ");

我会把实际价值提取给你(你真的需要吗?)

答案 1 :(得分:1)

您可以创建标记类。

这被认为是反模式,因为它们不如使用类层次结构,但由于您无法控制层次结构,因此您没有多少选择。

这样,您就可以了解通过网络服务发送的内容,而无需诉诸instanceof

class FooBar {
    public static enum Mode { FOO, BAR }
    Foo foo;
    Bar bar;
    Mode mode;
    FooBar(Foo foo) {
        mode = Mode.FOO;
        this.foo = foo;
    }
    FooBar(Bar bar) {
        mode = Mode.BAR;
        this.bar = bar;
    }

    public String getName() {
        switch(mode) {
            case FOO: foo.getName();
            case BAR: bar.getName();
            default: throw new IllegalStateException();
        }
    }

    public void setName(String name) {
        switch(mode) {
            case FOO: foo.setName(name); return;
            case BAR: bar.setName(name); return;
            default: throw new IllegalStateException();
        }
    }
    public Mode getMode() { return mode; }
}

答案 2 :(得分:1)

据推测,你无法控制生成的类(否则,它将是微不足道的!)。

另一种方法是创建一个帮助器类并使用反射来设置您需要设置的每个属性(参见How do I invoke a Java method when given the method name as a string?

答案 3 :(得分:0)

我不确定您的要求是什么,但您是否考虑过创建包含foo和bar实例的包装类的最简单的解决方案?

class FooOrBar {
    private Foo foo;
    private Bar bar;

    public setName(name) {
        if (foo != null) foo.name = name;
        if (bar != null) bar.name = name;
    }
}

您可以根据需要添加验证,以确保单个包装器仅引用一个项目。