抽象的工厂设计模式与泛型:在哪里是额外的解耦?

时间:2017-01-21 16:31:04

标签: generics design-patterns decoupling abstract-factory

问题/问题。

我试图尽可能多地解耦实现和接口/抽象类,以便能够轻松切换实现。

我了解到可行的方法是依赖注入,但在使用整个框架之前,我想实现/理解该机制。

我还了解到实现依赖注入的一种方法是使用抽象工厂。

我正在尝试在以下代码中使用它们,但我不知道在哪里可以在客户端和实现之间实现更多的解耦。我想我可能无法正确理解/实现工厂设计模式来解决这个问题。

样本情况

我们说我有:

  • 一个映射器,它是一个通用接口:

    public interface Mapper<A,B> { [mapper methods]}

  • 实现此映射器接口的具体类:

    JsonMapper implements Mapper<Json,ModelObject>{ [mapper methods implemented..] }

现在我想在第三个对象中使用映射器,例如:

OnlineRepo {
  // reference to an interface (which is good I guess)
  Mapper<Json, ModelObject> mMapper;

  // constructor needs a concrete Mapper<Json, ModelObject>
  OnlineRepo(Mapper<Json, ModelObject> jsonToModelMapper ){
    mMapper = jsonToModelObject;
  }

  // other OnlineRepo methods using mMapper, get, upsert etc etc...
  [...]
}

最后我的主要代码必须实现正确的具体类。 &lt; - 那是我不喜欢的。

main{
  JsonMapper mapper = new JsonMapper();  // reference to concrete JsonMapper

  OnlineRepo repo = new OnlineRepo(mapper); // inject concrete JsonMapper
}

工厂设计模式如何帮助我解耦这些物体?

  1. OnlineRepository不直接引用具体JsonMapper,它仅引用摘要Mapper<Json, ModelObject>。不是吗?

  2. 抽象工厂设计模式如何帮助我更多地解耦这些代码。

  3. 好像我总是需要在我的主程序中引用一个实现(如果不是JsonMapper的实现,JsonMapperFactory的实现?)。

  4. 为了更好地说明我没有看到这个的优点:

    psoeudo UML with abstract factory

    对此:

    psoeudo uml without abstract factory

    我希望能做什么:

    我希望能够在main(我的客户)中做到这一点:

    Mapper<Json, ModelObject> = GenericMapperFactory.getMapper() 这将自动提供JsonMapper。

    我也可以这样做 Mapper<xml, ModelObject> = GenericMapperFactory.getMapper()并获得正确的具体对象。

    声明

    我希望我的问题很清楚,如果没有,请不要犹豫告诉我,以便我可以继续努力。这些概念对我来说还不完全清楚,所以我很难写出明确的问题。

    提前感谢您的帮助。 最好的,安东尼

2 个答案:

答案 0 :(得分:1)

实例化具体对象的位置与创建的类耦合。在您的情况下,这是主要的。通过使用工厂模式,您可以将主要与Mapper接口的实现分离。你只知道工厂。现在再次对Mapper进行子类化并使用另一种Mapper不会影响您的main方法。

为了保护您的Main不受实现类的限制,我不建议使用工厂模式。 Main是您的程序启动的地方,因此负责创建一些对象并将它们组合在一起以引导您的应用程序。

在应用程序中动态创建对象或使用一些同时使用的对象时,应使用工厂(例如:窗口工厂(GUI))

如果您创建一个可以使用Qt或Cocoa GUI运行的应用程序,则必须确保框架之间的一致性。 QtFactory会创建QWidgets和表单,而CocoaFactory会创建CocoaWindows。应用程序的其余部分与使用的框架分离。如果你在main中安装一个QtFactory,你的Programm将使用Qt GUI运行,使用CocoaFactory它将是一个Cocoa GUI。这是抽象的工厂模式。它允许你交换实现类,而不用担心它们是否会混合(Cocoa窗口与QWidget)。

答案 1 :(得分:0)

关键点是否使用工厂,但是你应该使用依赖注入进行一些控制容器的反转。因此,您的存储库实例化将由整个容器完成,您将使代码与实现完全无关。

否则,如果您进行手动依赖注入,显然您需要手动实例化实现。

例如,使用具有依赖注入支持的控件容器的反转,您将注入您的存储库,并且您将自动获得映射器的工厂或抽象映射器:

public class WhoKnows
{
     public WhoKnows(IOnlineRepository repo)
     {
           // repo will come up with its dependencies already loaded
           // and its dependencies will also have their own dependencies already
           // loaded in cascade...
     }
}