我已经看到了一些类,其中接口具有方法声明,其子类类型的参数(实现类)如下所示:
接口A定义为具有方法setData的方法,该方法具有类型为AAbstract的参数,它是实现接口A的具体类AImpl的子类:
public interface A{
void setData(AAbstract ref);
}
我们实现了类AImpl:
public class AImpl implements A {
private AAbstract instance;
public void setData(AAbstract ref) {
this.instance= ref;
}
}
再次抽象实现,如:
public abstract class AAbstract extends AImpl {
public abstract void dummy(String msg);
}
个人我认为没有正确的设计想从设计角度了解专家评论。
答案 0 :(得分:0)
这种模式的一个大问题是耦合 - 类AImpl
和抽象类AAbstract
是紧密耦合和循环相关的。继承层次结构中的每个级别都知道其他级别,因此一个级别中的更改可能会影响其他级别。通常,您会尝试设计不依赖于或不了解其子女的课程。有一些例外情况,其中一个类的实现数量是事先知道的,并且通常不会改变,但它们很少见。在这种情况下,AAbstract
和AImpl
之间的循环依赖关系表明它们也可以合并为一个类。
说实话,我看不出模式会带来什么价值。 AImpl
包含AAbstract
的实例,其扩展AImpl
,因此还包含AAbstract
的实例......所以AAbstract
一直向下?我的猜测是在某种程度上存在空值,没有人喜欢null。
答案 1 :(得分:0)
答案就是使用更具描述性的实现名称。
AImpl
和AAbstract
表示您正在为单个实施创建接口。在这种情况下,YAGNI适用并且不需要抽象。抽象允许反转控制,允许您指定不同类型的A
。如果只有一个实现,则抽象几乎没用。当然,这只是在理论上,因为人们在测试中创建易于模拟的抽象。
抽象允许不同的实现。如果您使用AImpl
,您会为其他实现命名什么?
你可以使用ADefault
,这表明它是一个默认实现(如果其他实现不适合这个技巧,使用默认值),但这仍然是你指定的同样问题,只是有点淡化
问问自己:“如果我有多个实现,它们之间会有什么区别?为什么我需要多个实现?”。这将帮助您为每个实现找到更具描述性的名称,允许您命名抽象A
,然后根据它们存在的原因定义不同类型的A
。
给出一个使用A
的例子,我确信我可以很容易地找到更好的名称来实现。例如,Graphics
是抽象,OpenGL
和DirectX
是实现。这两种实现都是出于不同的目的而存在的,并且在它们的名称中进行了描述。