【问题标题】:Abstract Factory in Java - How to extend?Java中的抽象工厂-如何扩展?
【发布时间】:2011-07-20 09:09:03
【问题描述】:

我使用 java 库,coreAbstractFactory 负责 UI 组件。 MyApplication 使用核心并自定义 UI。因此,在 MyApplication 启动期间,我将 MyFactory 设置为 AbstractFactory 的一个实例。

class AbstractFactory {
  ...
  public static AbstractFactory getInstance();
  public abstract JButon createButton();
  public abstract JLabel createLabel();
  ...
}

class MyFactory extends AbstractFactory {
   ...
}

MyApplication.startup() {
  AbstractFactory.setInstance(new MyFactory())
}

我的问题是,我需要在 MyApplication 中创建例如 JList,但我无法在 AbstractFactory 中添加 public JList createJList(),因为我无法修改核心库。

我该怎么办?

案例一: 总是在 MyApplication 中调用 MyFactory.getMyFactoryInstance(),新的静态字段。

class MyFactory extends AbstractFactory {
   private static MyFactory myInstance = new MyFactory();
   public static getMyFactoryInstance() { return myInstance }
   ...
}

案例二: 总是在 MyApplication 中调用 MyFactory.getMyFactoryInstance(),使用 cast

class MyFactory extends AbstractFactory {
   public static MyFactory getMyFactoryInstance() { 
       if (getInstance() instanceOf MyFactory) {
           return (MyFactory) getInstance();
       }
       throw Exception();
   }
   ...
}

案例三: 使用两个工厂。对于 JButton 和 JLabels,使用 AbstractFactory,对于 JList,使用 SomeOtherFactory。

JButton button = AbstractFactory.getInstance().createButton();
JList list = SomeOtherFactory.getInstance.createList();

案例四:更好?我觉得我忽略了一些东西。

【问题讨论】:

    标签: java abstract-factory


    【解决方案1】:

    我将创建AbstractFactory 的抽象子类,它指定createJList() 方法并覆盖返回新抽象类类型的getInstance() 方法。然后,您可以在 MyFactory 类中实现逻辑,并遵守对接口(在本例中为抽象)而不是实现编程的原则

    示例代码:

    public abstract class MyAbstractFactory extends AbstractFactory {
     //you could implement AbstractFactory's abstract methods here
    
     public abstract JList createJList();
    }
    
    public class MyFactory extends MyAbstractFactory {
     private static MyAbstractFactory instance;
    
     private MyFactory() {}
    
     public JList createJList() {
      //implementation of method here
     }
     public static MyAbstractFactory getInstance() {
      if (instance == null) instance = new MyFactory();
      return instance;
     }
    }
    

    上面的例子使用了惰性实例化,如果代码不总是被使用并且没有在多线程应用程序中使用,这是非常棒的。但是,如果它以多线程方式使用,我将使用 MyFactory 的以下实现,它使用 双重检查锁定 来处理多个线程。

    public class MyFactory extends MyAbstractFactory {
     private volatile static MyAbstractFactory instance;
    
     private MyFactory() {}
    
     public JList createJList() {
      //implementation of method here
     }
     public static MyAbstractFactory getInstance() {
      if (instance == null) {
       syncronized(MyFactory.class) {
        if (instance == null) instance = new MyFactory();
       }
      }
      return instance;
     }
    }    
    

    无论哪种实现,用法都将保持不变。

    用法:

    MyAbstractFactory factory = MyFactory.getInstance();
    factory.createJList();
    

    【讨论】:

    • 我应该如何实现getInstance()?我应该使用 cast - 可能不安全,还是应该引入 MyFactory 类型的新静态字段?顺便说一句:我想 getInstance() 应该是静态方法。
    • @jk_ 我已更新我的答案以包括 getInstance 代码和所有其他必需的代码段(私有构造函数、静态 MyAbstract Factory 变量)。请参见上文。
    • 我喜欢 MyAbstractFactory 的想法。但有人反对该解决方案:将有两个静态成员:AbstractFactory 类型的“实例”(来自 AbstractFactory)和 MyAbstractFactory 类型的“实例”(来自 MyAbstractFactory)。有人就是不喜欢这个主意。
    • @jk_ MyFactory 中的 getInstance 方法将覆盖 AbstractFactory 中设置的静态 getInstance 方法。
    • 您不能使用 MyFactory.getInstance(),因为它会使您的应用程序与 MyFactory 紧密相关。我使用 MyAbstractFactory 以便有人可以“注入”另一个实现。如果我有方法 MyAbstractFactory.getInstance(): MyAbstractFactory,我需要 MyAbstractFactory 类中 MyAbstractFactory 类型的私有静态字段实例和该字段的静态设置器。
    【解决方案2】:

    由于您需要不同的工厂来构建不同的东西,您是否考虑过合并泛型?

    interface Factory<T> {
      ...
      T create();
      ...
    }
    

    只需为您需要创建的每种类型的事物创建一个类型化工厂。例如:

    class JButtonFactory implements Factory<JButton> {
        public JButton create() {
            return new JButton();
        }
    }
    

    【讨论】:

    • 对不起,我不明白你的意思。这如何取代抽象工厂模式?假设核心库使用这些泛型,我怎样才能让核心使用 MyJButton,而不是默认的 JButton?
    猜你喜欢
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-17
    • 2019-01-22
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    相关资源
    最近更新 更多