创建接口的引用并为其分配实现对象被认为是一个干净的设计决策

时间:2015-05-05 20:10:13

标签: java oop inheritance interface

我有一个名为Tiger的基类

class Tiger implements Attack{
@Override
public void pounce(int intensity){
}
@Override
public void threatLevel(int level){
}

}

攻击界面:

Interface Attack{
void pounce(int intensity);
void threatLevel(int level);
 }

另一个子类SiberianTiger

class SiberianTiger extends Tiger{
public void setupSiberianTiger(int intensity,int level){
  pounce(intenisty);
  threatlevel(level);
}

}

public static void main(){
Attack attack =new SiberianTiger();
//setup the Siberian Tiger meow >.<
((SiberianTiger)attack).setupSiberianTiger(4,5);
}

所以我的问题是,按照我的方式初始化SiberianTiger实例是一个很好的设计决策。我该如何改进呢 ((SiberianTiger)攻击).setupSiberianTiger(4,5);

3 个答案:

答案 0 :(得分:4)

您应该使用您知道将使用可用字段和方法的类型声明变量。在这种情况下,声明这一点没有任何好处:

Attack attack = new SiberianTiger();
((SiberianTiger)attack).setupSiberianTiger(4,5);

最好将变量声明为SiberianTiger

SiberianTiger siberianTiger = new SiberianTiger();
siberianTiger.setupSiberianTiger(4,5);

在这一小段代码中无法看到使用超类或接口的好处。例如,如果您有Attack s:

的集合,则可以看到它
List<Attack> attackList = new ArrayList<>();

SiberianTiger siberianTiger = new SiberianTiger();
siberianTiger.setupSiberianTiger(4,5);
attackList.add(siberianTiger);

for (Attack attack : attackList) {
    attack.<doSomething>();
}

当然,还有其他方法可以改进这种设计,比如为SiberianTiger创建一个适当的构造函数,传递变量,应用工厂模式或构建器等。

答案 1 :(得分:1)

我会写一个工厂类并避免演员。

客户应该处理Attack个引用,而不是具体的子类型。

我同意关于界面名称的评论:好名字很重要。我更喜欢Attacker

public class AttackerFactory {
    private static final AttackerFactory instance = new AttackerFactory();

    private AttackerFactory() {}

    public static AttackerFactory getInstance() { return instance; }

    public Attack createAttacker(Class<Attack> attackerClass, int intensity, int threatLevel) {
        // Create what you want here
    }
}

答案 2 :(得分:1)

没有。需要你施放的设计并不干净。幸运的是,在这种情况下,有一个简单的替代方案:

public static void main(){
    SiberianTiger attack = new SiberianTiger();
    //setup the Siberian Tiger meow >.<
    attack.setupSiberianTiger(4,5);
}

更一般地说,您应该始终声明与您的使用要求一致的最不具体类型 。在您的情况下,您希望使用特定于类SiberianTiger的初始化方法,以便您应该声明的类型。

您当然可以将SiberianTiger对象传递给接受任何类型Attack的方法,或将其分配给此类变量等。这是一个完全不同的事情。< / p>