这是一个反模式还是违反了一些设计原则呢?

3

我尝试着使用设计模式和原则,并有一个问题。事先,抱歉我的糟糕的编码习惯!

我有一个接口,就像在这个例子中的ITest:

public interface ITest
{
    public void method1();
}

然后将方法和字段(如果有)实现到一个具体的B类中,如下所示:

public class B implements ITest
{
    //This is the method from the interface
    @Override
    public void method1()
    {
        System.out.println("method1");
    }

    //This is another method in class B
    public void method2()
    {
        System.out.println("method2");
    }
}

现在我将应用程序代码放入如下所示的代码块中:
public class Main 
{
    public static void main(final String args[]) throws Exception 
    {
        //One principle says:
        //programm to an interface instead to an implementation
        ITest test = new B();

        //method from interface
        test.method1();
        //this method is not accessible because not part of ITest
        test.method2();     //compile-time error
    }
}

你会发现B类中的method2()方法无法使用,因为它不在ITest接口中。那么如果我需要这个“重要”的方法呢?有几种可能性。我可以在接口中抽象它,或者将B类变成抽象类并继承到另一个类中等等,或者在main()方法中引用它:

B test = new B();

但这将违反原则。因此,我修改了接口如下:
public interface ITest
{
    //A method to return the class-type B
    public B hook();
    public void method1();
}

将实现放入B类中:

public class B implements ITest
{
    //this returns the object reference of itself
    @Override
    public B hook()
    {
        return this;
    }

    //This is the method from the interface
    @Override
    public void method1()
    {
        System.out.println("method1");
    }

    //This is the 'important' method in class B
    public void method2()
    {
        System.out.println("method2");
    }
}

现在,在我的main()方法中,我可以使用一个小钩子或链接机制调用这两个方法,而不需要引用一个新的对象,也不会违反设计原则,也不需要额外的类来扩展或抽象。

public class Main
{
    public static void main(final String args[])
    {
        //programm to an interface instead into an implemintation
        ITest test = new B();
        //method from interface
        test.method1();
        //method2 will not be accessible from ITest so we referencing B through a method hook()
        //benefits: we don't need to create extra objects nor additional classes but only referencing
        test.hook().method2();
        System.out.println("Are they both equal: "+test.equals(test.hook()));
    }
}

此外,我可以封装、继承和抽象其他方法、字段等。这意味着我可以创建更复杂和灵活的层次结构。
我的问题是: 这是一种反模式、不良设计原则还是我们可以从中受益?
谢谢观看。 :-)

你在 Code Review 上有更好的机会得到答案。 - Federico klez Culloca
@Federuco klez Culloca,谢谢你提供的提示。 - PriNova
2个回答

3

这是一种反模式,不好的设计原则,我们可以从中获益吗?

是的,这是一种不好的模式。

问题在于ITestB耦合度过高。假设我想创建一个新的ITest实现 - 我们称其为C

public class C implements ITest
{
    @Override
    public B hook()
    {
        // How do I implement this?
    }

    @Override
    public void method1()
    {
        System.out.println("method1");
    }
}

我们没有理智的方法来实现这个方法。唯一合理的做法是返回null。这样做会迫使我们接口的任何用户不断进行防御性的空值检查。

如果他们每次使用该方法的结果之前都要进行检查,那么他们可能就只需要进行instanceof检查并转换为B。那么你增加了什么价值呢?你只是让接口变得更不协调和更加混乱。


2

给由B实现的接口ITest添加返回B的方法绝对是一个糟糕的设计选择,因为它强制其他实现ITest的类也要返回B,例如:

public class C implements ITest {
    @Override
    public B hook()
    {
        return // What do I return here? C is not a B
    }
    ...
}

你的第一个选择更好:

B test1 = new B();
C test2 = new C();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接