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

Java 如何使用静态工厂方法创建抽象类?,java,swing,static-methods,factory-pattern,effective-java,Java,Swing,Static Methods,Factory Pattern,Effective Java,我有一个“标准的”JPanel,里面有两个面板。我试图创建一种模板类,然后扩展它并实现内容。问题是哪种方式可以实现它 下面的代码是我试图让它工作的,但我刚刚开始阅读有效的Java书籍,我不熟悉静态工厂方法。特别是想把它们抽象出来 这本书中的一些小贴士是我想特别遵循的 考虑静态工厂方法,而不是构造函数 重组合轻继承 与抽象类相比,更喜欢接口 但是我找不到一个关于这些问题的好的解决方案(没有它们:p) 请随时询问您是否需要关于代码其他部分的更多信息。Java静态方法不能是抽象的——需要更长时间的

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

下面的代码是我试图让它工作的,但我刚刚开始阅读有效的Java书籍,我不熟悉静态工厂方法。特别是想把它们抽象出来

这本书中的一些小贴士是我想特别遵循的

  • 考虑静态工厂方法,而不是构造函数
  • 重组合轻继承
  • 与抽象类相比,更喜欢接口
但是我找不到一个关于这些问题的好的解决方案(没有它们:p)


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

Java静态方法不能是抽象的——需要更长时间的讨论

现在,让我们分解您的构造:您的最终结果应该是一个具有两个子项的
JPanel
,也是
JPanel
,其自身构造取决于父项
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()
的构造函数

Java静态方法不能是抽象的——需要更长的讨论

现在,让我们分解您的构造:您的最终结果应该是一个具有两个子项的
JPanel
,也是
JPanel
,其自身构造取决于父项
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()
的构造函数

祝贺您阅读了《高效Java》,并尝试将其付诸实践。它将为您的代码带来更多的可用性和清晰性

现在,让我们看看:

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

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

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

  protected abstract return-type myBehaviour2(parameters...)
  {
      ...
  }
}
2.如果从施工时收到的参数来看,有一些行为是
中央页面不知道的,必须在对象生命周期内的任何时候(在构造函数结束后)委托给第三方,适当的模式应该是一个抽象类,每个所需的行为都有一个抽象方法:

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

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

  protected abstract return-type myBehaviour2(parameters...)
  {
      ...
  }
}
当然,每个非抽象子类都必须提供实现其相应方法的每个必需行为


3.静态工厂方法的目标是非抽象类。它的目的是决定是否必须创建一个对象(可能一个现有的对象可以重用,就像在singleton模式中一样),并最终决定必须实例化哪个类(可能是所有者类本身,也可能是某个子类)。

祝贺您阅读了《有效的Java》并试图将其付诸实践。它将为您的代码带来更多的可用性和清晰性

现在,让我们看看:

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

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

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

  protected abstract return-type myBehaviour2(parameters...)
  {
      ...
  }
}
2.如果从施工时收到的参数来看,有一些行为是
中央页面不知道的,必须在对象生命周期内的任何时候(在构造函数结束后)委托给第三方,适当的模式应该是一个抽象类,每个所需的行为都有一个抽象方法:

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

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

  protected abstract return-type myBehaviour2(parameters...)
  {
      ...
  }
}
当然,每个非抽象子类都必须提供实现其相应方法的每个必需行为


3.静态工厂方法的目标是非抽象类。它的目的是决定是否必须创建一个对象(可能现有的对象可以重用,就像在singleton模式中一样),并最终决定必须实例化哪个类(可能是所有者类本身,也可能是某个子类)。

我想,你想解决什么,我有一个带有默认静态工厂方法的抽象类,但不可能在抽象类上添加静态方法。所以我想找一个标准的工作环境。更好?提供静态工厂方法而不是构造函数的基本思想是隐藏实现。这些实现隐藏在私有类或匿名类中的某个地方。您的方法看起来更像抽象工厂方法。您应该提供一个通用的factory界面,然后可用于自定义面板。尽管如此,如果需要,您仍然可以将工厂方法的“默认”实现作为静态方法提供。@kaetzacoatl我想我不理解您的解决方案。如何提供带有接口的默认实现?请用您的建议创建一个答案。您想解决什么问题?我想,我有一个带有默认静态工厂方法的抽象类,但不可能在抽象类上添加静态方法。所以我想找一个标准的工作环境。更好?提供静态工厂方法而不是构造函数的基本思想是隐藏实现。这些实现隐藏在私有类或匿名类中的某个地方。您的方法看起来更像抽象工厂方法。你应该提供一个通用的工厂界面