如何使用静态工厂方法创建抽象类?

时间:2016-08-21 12:18:57

标签: java swing static-methods factory-pattern effective-java

我有一个"标准" JPanel里面有两个面板。我试图创建一种模板类,然后扩展它并实现内容。问题是关于实现它的方式。

下面的代码是我试图让它发挥作用但我刚刚开始阅读Effective Java书籍并且我不熟悉静态工厂方法。特别试图抽象它们。

本书中我试图特别关注的一些提示是

  • 考虑静态工厂方法而不是构造函数
  • 赞成合成而不是继承
  • 首选接口到抽象类

但我无法找到一个尊重这些要点的好方法(没有它们:P)。

public abstract class CentralPage {

    static JPanel getInstance() {
        JPanel container = new JPanel();
        container.setBackground(Color.white);
        container.setBorder(
                BorderFactory.createCompoundBorder(new LineBorder(Color.BLACK), new EmptyBorder(10, 10, 10, 10)));
        container.setMinimumSize(new Dimension(960, 400));
        container.setPreferredSize(new Dimension(960, 400));
        container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));

        JPanel up = getUp(container);
        container.add(up);
        JPanel down = getDown(container);
        container.add(down);
        return container;
    }

    abstract JPanel getDown(JPanel container);

    abstract JPanel getUp(JPanel container);

}

随意询问您是否需要有关代码其他部分的更多信息。

2 个答案:

答案 0 :(得分:3)

Java静态方法不能是抽象的 - 更长的讨论here

现在让我们分解你的结构:你的最终结果应该是JPanel,有两个孩子,也是JPanels,他们自己的结构取决于父JPanel。您希望在静态工厂方法中完成此构造。

如果这是正确的,这可能是一个解决方案:

public interface UpDown{
    public JPanel getUp(JPanel parent);
    public JPanel getDown(JPanel parent);
}

public class CentralPage{
    static JPanel getInstance(UpDown components){
        JPanel container = new JPanel();
        container.setBackground(Color.white);
        container.setBorder(
                BorderFactory.createCompoundBorder(new LineBorder(Color.BLACK), new EmptyBorder(10, 10, 10, 10)));
        container.setMinimumSize(new Dimension(960, 400));
        container.setPreferredSize(new Dimension(960, 400));
        container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));

        JPanel up = components.getUp(container);
        container.add(up);
        JPanel down = components.getDown(container);
        container.add(down);
        return container;
    }
}

更接近原始提案的另一种解决方案是:

public abstract class CentralPage{

    private static CentralPage page;

    protected JPanel container;

    protected CentralPage(){
        container = new JPanel();
        container.setBackground(Color.white);
        container.setBorder(
               BorderFactory.createCompoundBorder(new LineBorder(Color.BLACK), new EmptyBorder(10, 10, 10, 10)));
        container.setMinimumSize(new Dimension(960, 400));
        container.setPreferredSize(new Dimension(960, 400));
        container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));

        JPanel up = getUp(container);
        container.add(up);
        JPanel down = getDown(container);
        container.add(down);
    }

    static JPanel getInstance(){
        if(page==null){
            page=new CentralPage();
        }
        return page.getContainer();
    }

    abstract JPanel getDown(JPanel container);

    abstract JPanel getUp(JPanel container);

    protected JPanel getContainer(){
         return this.container;
    }
}

这种(相当反模式)方法的缺点是你需要记住在具体类上创建一个调用super()的构造函数;

答案 1 :(得分:0)

我祝贺阅读" Effective Java"并试图将其付诸实践。它将为您的代码带来更多可用性和清晰度。

现在,让我们看看:

1.首先,如果你的抽象CentralPage在构造时只需要两个Panel对象,那么最简单的方法就是一个非抽象类,在其构造函数中有两个参数

public class CentralPage
{
  public CentralPage(Panel up, Panel dn)
  {
      ...
  }
}

2.如果从构造中接收参数开始,有一些行为是CentralPage所不知道的,必须在对象生命周期内的任何时间委托给第三方(在构造函数结束之后),正确的模式将是一个抽象类,每个必需行为都有一个抽象方法

public abstract class CentralPage
{
  protected CentralPage(...)
  {
      ...
  }

  protected abstract return-type myBehaviour1(parameters...)
  {
      ...
  }

  protected abstract return-type myBehaviour2(parameters...)
  {
      ...
  }
}

而且,对于corse,每个非抽象子类必须提供实现其相应方法的每个必需行为。

3.静态工厂方法针对非抽象类。其目的是决定是否必须创建一个对象(可能会重用现有对象,如单例模式),最终决定必须实例化哪个类(也许是所有者类本身,或者可能是某些子类)。