Java-接口过多吗?

时间:2018-11-14 00:06:37

标签: java class design-patterns dependency-injection object-oriented-analysis

我已经编程了两年了。对于我来说,接口似乎一直是一个困难的话题。将尽可能多的功能抽象到接口中是一种好习惯吗?

我从来没有完全理解它们的好处。我一直以为“为什么不正常地编写方法”。它们只是方法。然后,我开始学习依赖注入,以及它如何真正简化代码,使构造函数成为该类与外界联系的主要点。

但是,最近,我开始重新考虑接口以及如何像类型一样抛出接口,而不仅仅是标记方法的一种可爱方式。

因此,在我第一次使用Java接口进行真正的实验时,我制作了这个示例,我想知道的是:

对于了解接口功能的Java开发人员来说,我编写的这段代码片段说明了一种好的模式还是一种思路?到目前为止,基本上是好的代码吗?我只想知道我是否走在正确的道路上。明天我有工作要做第二次面试,并且只有在我走上正确的道路时,我才想在面试中提出这一认识。

代码如下:

interface Fightable{
void kick(Fightable enemy);
void punch(Fightable enemy);
void takeDamage(Fightable enemy, String typeOfStrike);
void strikeEnemy(Fightable enemy, String typeOfStrike);
}

interface CanEat{
void chew();
void swallow();
}

interface MotherShip{
int motherShipBoost = 50;
String getColony();
void sendHelp(int[] location);
String buildMoreShips(int amount);
void flyToNewSystem(String newSystem);
int[] beamDownRandomly();
}

interface Animatable{
void animateChew(CanEat eater);
void animateSwallow(CanEat eater);
void animateMove(Moveable mover);
void animateRevive(CanEat eater);
void animateStrike(Fightable striker, Fightable receiver, String typeOfStrike);
}

interface Moveable{
void setNewLocation(int []newLocation);
int[] getLocation();
void move();
}

public class GameCharacter implements Fightable, CanEat, Moveable{

private int health;
private String name;
private int[] location;
private String stamina;
private String origin;
private String colony;
private Animatable animator;
private MotherShip motherShip;
private boolean isRecruited;

public GameCharacter(MotherShip motherShip, String name, Animatable animator){
    this.motherShip = motherShip;
    this.animator = animator;
    this.name = name;
    this.location=this.motherShip.beamDownRandomly();
    this.colony = this.motherShip.getColony();
}


@Override
public void kick(Fightable enemy) {
    strikeEnemy(enemy, "KICK");

}



@Override
public void punch(Fightable enemy) {
    strikeEnemy(enemy, "PUNCH");
}

@Override
public void takeDamage(Fightable enemy, String typeOfHit) {
    this.health = this.health - 3;
    animator.animateStrike(enemy, this, typeOfHit);
    if(this.health < 10){
        motherShip.sendHelp(this.location);
    }
}

@Override
public void strikeEnemy(Fightable enemy, String typeOfStrike) {
    enemy.takeDamage(this, typeOfStrike);
    animator.animateStrike(this, enemy, typeOfStrike);
}

@Override
public void chew() {
    animator.animateChew(this);

}

@Override
public void swallow() {
    animator.animateSwallow(this);
    health = health + 10;
    animator.animateRevive(this);
}

@Override
public void setNewLocation(int[] newLocation) {
    this.location = newLocation;
}

@Override
public int[] getLocation() {
    return this.location;
}

@Override
public void move() {
    animator.animateMove(this);
}
}

看起来像我有正确的主意吗?

谢谢您的反馈

-T

2 个答案:

答案 0 :(得分:2)

首先,存在用于实现其中描述的所有非默认方法的接口。可以很容易地用抽象类代替。但是,为了更轻松地进行清理,已实现了接口。

接口似乎很合逻辑且更易于使用,所以没有太多接口。但是,一旦您或您的同事为获取照片而头痛,那就太麻烦了。

使用接口作为简化清理和结构化流程的一种额外方式。

此外,在类的情况下,java不支持多重继承。因此,通过使用接口,您可以像在示例中那样具有多重继承。

非常好的工作,祝您面试顺利!

答案 1 :(得分:0)

我将尽最大努力尽力回答您的问题。

1。

将尽可能多的功能抽象到接口中是一种好习惯吗? 让我们从基础开始 a)请记住,接口不过是“合同”,即实现接口的参与者基本上承诺按照合同条款和条件兑现和交付的承诺。 b)接口在代码中是出色的设计工具,从本质上讲,使生产者和参与者可以专注于高层交互,而不必担心实现细节。

在CS基础知识外行的术语中,接口承诺符合性,本质上是三件事。 1.保证上述功能/操作/功能/方法可用 2.此功能接受所述约定输入 3.该功能(如果实施)将产生所述结果。

因此,当一项服务(类/肥皂消息等)提供实现接口的意图时,它公开同意“合同”的这三个条款,并且与之的任何背离均违反合同。

2。

是的,您是完全正确的,当涉及SOLID design principles中的Ioc(控制反转)时,接口确实发挥了作用,它允许IoC容器解析(提供)并服务于合适的参与者(实现)。它通常在运行时遵守合同,因此使系统开发人员不必担心实现细节。

但是,也许只有在实现service locator pattern时才能实现Ioc的好处,因此,“开发人员或团队如何将从使用接口作为设计工具中受益?”成为一个重要的问题。

单个开发人员 例如,我正忙于编写一个新的软件系统,并且在白天,我全神贯注于想为用户提供的功能,也许能够从一般意义上管理他们的待办事项清单,能够“创建”新的待办事项,“清除”现有项目并从待办事项集合中“删除”项目。现在,有几种方法可以实现这些功能中的每一个,并且变得懒惰,我宁愿花下一周的时间来实现其中一个功能,但我可能会忘记最初的想法并最终实现基于自己的功能随着时间的流逝,我会根据自己的影响来训练自己并坚持我最初的想法,我宁愿提前起草一份此功能的合同,而无需实际实施它,这使我可以模拟这些功能,而不是实际实施它们。因此,通过使用界面,我奠定了接下来几周需要实现的目标的基础,我可以每隔一天回到它并完成我的功能而不会违反我的诺言……这将我们带入了下一个主题我现在不会过多地研究Open Close principles(SOLID中的O),它基本上说我的设计不接受外部更改,但可以接受内部更改,也可以接受扩展(添加)事件。因此我可以在不中断现有合同的情况下将新功能添加到待办事项服务中,并且可以更改其实现行为,但不能更改现有功能的形状。

团队合作 我与Lindile和Selebalo合作实施虚拟卡系统,并且由于工作量过多,我们决定我将专注于核心银行系统(余额分类帐),而Lindile将专注于VC的存款,而Selebalo则专注于虚拟银行的存款。风险投资的存款。在最初的设计过程中,我们从核心银行开始,由内而外进行设计,并描述可用于更新客户帐户的操作,经过数小时的讨论,我们决定核心银行系统将提供两种功能,一种用于添加将钱存入一个接受金额的帐户,称为“贷方”,扣除或减少也接受金额的客户帐户的“借方”。但是,由于核心除了借方和贷方外还必须处理许多其他事情(客户信用资料,AML等),因此可能要花一些时间才能让我说这些人可以集成并测试他们的代码,因此我们决定签订一份拥有

的核心银行
public interface ICoreBankingServices{

Balance Debit(decimal amount,Currency c);
Balance Credit(decimal amount, Currency c);

}

现在,Lindile和Selebalo可以假设我会遵守合同,并选择模拟或模拟Debit and Credit的结果,直到我们都准备好进行集成和测试,因此我的功能对他们没有开发依赖性工作,这是一件积极的事情。

我希望这些示例能够说明使用接口,设计工具和依赖项解耦机制的一些基本好处。

我不是Java所期望的,但是如果游戏角色必须战斗,吃饭和移动,那您就走对了。您只需要留意要进行的去耦级别(与规范化相同),以增加复杂性为代价,但是对此没有任何指导,只要事情不会变得太复杂,就可以在在逻辑上可能有许多接口... 在涉及多个实现继承时,只是没有采用相同的想法,但这是个人观点 :)

您最终将不得不缴税,并进一步了解设计模式以及它们试图解决或简化的内容,以便加深对设计更好系统的理解。