【问题标题】:How should this class be modified in order to follow the DIP (Dependency Injection Principle)?应该如何修改这个类以遵循 DIP(依赖注入原则)?
【发布时间】:2016-02-07 15:44:26
【问题描述】:

如何修改这个类以遵循 DIP(依赖倒置原则)以删除构造函数中的两个 ArrayList 依赖项?接口应该如何?

让我感到困惑的是,新的引用指向ArrayList<type>,而不仅仅是类的构造函数。而且我不知道如何处理这种情况......

package mvc.controllers;

import java.util.ArrayList;
import mvc.models.AbstractModel;
import mvc.views.AbstractViewPanel;

public abstract class AbstractController {

    private ArrayList<AbstractViewPanel> registeredViews;
    private ArrayList<AbstractModel> registeredModels;

    public AbstractController() {
        registeredViews = new ArrayList<AbstractViewPanel>();
        registeredModels = new ArrayList<AbstractModel>();
    }

    public void addModel(AbstractModel model) {
        registeredModels.add(model);
        model.addPropertyChangeListener(this);
    }

    public void removeModel(AbstractModel model) {
        registeredModels.remove(model);
        model.removePropertyChangeListener(this);
    }

    public void addView(AbstractViewPanel view) {
        registeredViews.add(view);
    }

    public void removeView(AbstractViewPanel view) {
        registeredViews.remove(view);
    }
    ...
}

【问题讨论】:

  • 做什么?这个问题相当模糊和不清楚,肯定是错别字和可能缺乏理解。您能否重新表述您想了解的内容,并更深入地了解您正在苦苦挣扎的地方?
  • 完成了,我希望现在更清楚了。原谅我的语法错误。英语不是我的第一母语/语言。
  • 本指南misko.hevery.com/code-reviewers-guide 有一些非常好的示例,也涵盖了 DI
  • DIP 是依赖倒置原则。你的错误很容易犯,因为依赖注入是一种满足 DIP 的技术。

标签: java model-view-controller dependency-injection refactoring dependency-inversion


【解决方案1】:

要以 Dependency Inversion 方式执行此操作,您可以执行以下操作之一:

  1. 对列表的依赖在构造函数中给出:

    public abstract class AbstractController {
    
    private List<AbstractViewPanel> registeredViews;
    private List<AbstractModel> registeredModels;
    
    public AbstractController(List<AbstractViewPanel> registeredViews, List<AbstractModel> registeredModels) {
        this.registeredViews = registeredViews;
        this.registeredModels = registeredModels;
    }
    
  2. 为列表添加修改器(设置器):

    public abstract class AbstractController {
    
    private List<AbstractViewPanel> registeredViews;
    private List<AbstractModel> registeredModels;
    
    public AbstractController() {
    }
    
    public void setRegisteredViews(List<AbstractViewPanel> views) {
       this.registeredViews = views;
    }
    
    public void setRegisteredModels(List<AbstractModel> models) {
       this.registeredModels = models;
    }
    

顺便说一句,我将 ArrayLists 更改为 Lists。无需引入对 List 实现的依赖。

【讨论】:

  • 非常感谢看到不止一种方法:)谢谢。也考虑一下我对 artbrisol 的回复。两者都非常有用!
【解决方案2】:

目前还不清楚您要删除什么依赖项,但如果您想删除显式 ArrayList 实例化,可以使用构造函数注入:

private final List<AbstractViewPanel> registeredViews;
private final List<AbstractModel> registeredModels;

public AbstractController(final List<AbstractViewPanel> registeredViews,
        final List<AbstractModel> registeredModels) {
    this.registeredViews = registeredViews;
    this.registeredModels= registeredModels;
}

【讨论】:

  • 我认为我必须创建接口来注入 Arraylists 实例......但这不是重点。这些接口将帮助我隔离或几乎隔离(丢失耦合)方法 addModel、addView、removeModel、viewModel 的实现......但如果我只想正确地外部化数组(减少依赖)则不需要这样做(减少依赖)模型和视图方法是这个 AbstractController 类实现的一部分。对吗?
【解决方案3】:

我不会将 List 注入到对象中,从而破坏封装,只是为了通过模拟列表来对其进行单元测试。 List 不是外部依赖项。它是类内部的一部分。

如果您想对此类进行单元测试,请测试使用存储在列表中的对象的方法是否确实按照应有的方式使用它们。您还应该测试当您更改已添加到控制器的模型的属性时是否调用了 propertyChange 方法。

或者您可以添加 getView()getModels() 方法(可能受保护),以测试添加是否按预期工作。

【讨论】:

  • 那你是指我试图解决一个不存在的问题? :D 我制造了这个问题......我也喜欢你所指的。但是,我也希望能够做这样的事情......无论它是否更正确,在这种情况下可能不是......但可以很好地适应其他代码。
猜你喜欢
  • 2017-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多