Javaclassinheritance/interface实现原理

Java class inheritance/interface implementation principle

我不确定在特定情况下使用继承/接口实现。

在我的简单 Spring MVC 应用程序中,我有 @Entity class TennisPlayer,它继承自抽象 class Player(TennisPlayer 添加了一些属性)。

另外我还有class TennisPlayerForm,它继承自abstract class PlayerForm(TennisPlayerForm 又增加了一些属性)。

用户在.jsp页面填写关于网球运动员的表格,TennisPlayerForm对象用于表示填写的值,然后在此对象的基础上创建TennisPlayer对象并保存到数据库中。

TennisPlayer 对象的创建由 class TennisPlayerDbService 负责。 class 是 PlayerService 接口的实现。

我有以下处理请求的@Controller:

@Controller
public class NewPlayerController {

    @Resource(name="tennisPlayerService")
    private PlayerService playerService;


    //omitted RequestMethod.GET handler method


    @RequestMapping(value = "/newplayer", method = RequestMethod.POST)
    public String newplayer(Locale locale, @ModelAttribute("tennisPlayerForm") @Valid TennisPlayerForm tennisPlayerForm,
        BindingResult result, RedirectAttributes redirectAttributes) {

        playerService.createPlayer(tennisPlayerForm);

        return "redirect:/allplayers";
    }
}

我的部分源代码如下所示:

public interface PlayerService {

    public void createPlayer(PlayerForm playerForm);
}

@Service(value="tennisPlayerService")
public class TennisPlayerDbService implements PlayerService {

    private TennisPlayerDAO dao;

    @Autowired
    public void setDao(TennisPlayerDAO dao) {
        this.dao = dao;
    }

    @Override
    public void createPlayer(PlayerForm playerForm) {
        TennisPlayerForm tennisPlayerForm = null;

        if (playerForm instanceof TennisPlayerForm) {
            tennisPlayerForm = (TennisPlayerForm) playerForm;
        }
        else {
            throw new IllegalArgumentException("Must be of type TennisPlayerForm.");
        }


        TennisPlayer player = new TennisPlayer();

        player.setName(tennisPlayerForm.getName());
        player.setSurname(tennisPlayerForm.getSurname());
        player.setAge(tennisPlayerForm.getAge());
        player.setRacket(tennisPlayerForm.getRacket());
        player.setRanking(tennisPlayerForm.getRanking());
        player.setSponsor(tennisPlayerForm.getSponsor());
        player.setCoach(tennisPlayerForm.getCoach());
        player.setClub(tennisPlayerForm.getClub());

        dao.saveAndFlush(player);
    }
}

在这种情况下,当 PlayerService (TennisPlayerDbService) 的具体实现需要特定 class 的实例时,尽管这些潜在的 classes 具有共同的父级,但在这种情况下使用继承和接口实现是否合理?

通常您的服务不需要知道您正在使用表单。您的表单纯粹是为了成为您网页的模型-视图-控制器架构中的模型而创建的。 (您的 jsp 是视图,您的控制器是 c 部分)

您是否还打算使用 TennisPlayer 以外的其他类型的播放器?如果不是,这一切似乎都是过早的优化,您应该尽可能简单。

最后我根据您的评论和回答解决了我的问题。

我删除了 PlayerForm 摘要 class、TennisPlayerForm,并在 @Entity classes Player 和 Tennis Player 中混合了 javax.validation 和 javax.persistence 注释。

之前提到的代码现在看起来像这样:

@Controller
public class NewPlayerController {

    @Resource(name="tennisPlayerService")
    private PlayerService<TennisPlayer> playerService;

    //omitted RequestMethod.GET handler method  

    @RequestMapping(value = "/newplayer", method = RequestMethod.POST)
    public String newplayer(Locale locale, @ModelAttribute("tennisPlayer") @Valid TennisPlayer tennisPlayer,
        BindingResult result, RedirectAttributes redirectAttributes) {

        if(result.hasErrors()) {
            return "newplayer";
        }

        playerService.createPlayer(tennisPlayer);

        MessageUtil.flash(locale, redirectAttributes, "success", "signup.success");

        return "redirect:/allplayers";

    }
}

public interface PlayerService<T extends Player> {

    public void createPlayer(T player);

    public List<T> getAllPlayers();
}

@Service(value="tennisPlayerService")
public class TennisPlayerDbService implements PlayerService<TennisPlayer> {

    private TennisPlayerDAO dao;

    @Autowired
    public void setDao(TennisPlayerDAO dao) {
        this.dao = dao;
    }

    @Override
    public void createPlayer(TennisPlayer player) {     
        dao.saveAndFlush(player);
    }

    @Override
    public List<TennisPlayer> getAllPlayers() {
        return dao.findAll();
    }
}