简体   繁体   English

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

[英]How to create an abstract class with static factory method?

I have a "standard" JPanel with two panels inside. 我有一个带有两个面板的“标准” JPanel I was trying to create a kind of template class and then extend it and implement the content. 我试图创建一种模板类,然后对其进行扩展并实现其内容。 The question is about which would be the way to implement it. 问题在于,将采用哪种方式实施它。

The code below is what I'm trying to make it work but I've just started to read the Effective Java book and I'm not familiar with static factory method. 下面的代码是我试图使其起作用的代码,但是我刚开始阅读有效的Java书,并且我对静态工厂方法不熟悉。 Specially trying to abstract them. 特别是尝试抽象它们。

Some tips from the book that i'm trying to follow specially are 我要特别遵循的书中的一些技巧是

  • Consider static factory methods instead of constructors 考虑使用静态工厂方法而不是构造方法
  • Favor composition over inheritance 偏爱继承而不是继承
  • Prefer interfaces to abstract classes 优先于抽象类的接口

but I couldn't find out a good solution respecting these points (and without them :P). 但是我找不到一个尊重这些观点的好的解决方案(没有它们: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);

}

Feel free to ask if you need more information about other parts of code. 随意询问您是否需要有关代码其他部分的更多信息。

A Java static method cannot be abstract -- longer discussion here . Java静态方法不能是抽象的- 在此进行更多讨论。

Now let's break down your construction: your end result should be a JPanel with two children, also JPanels , whose own construction depends on the parent JPanel . 现在让我们分解一下构造:您的最终结果应该是一个有两个孩子的JPanel ,也是JPanels ,其自身的构造取决于父JPanel You would like this construction to be done in static factory method. 您希望此构造以静态工厂方法完成。

If that is correct, this could be a solution: 如果那是正确的,这可能是一个解决方案:

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;
    }
}

Another solution closer to your original proposal would be like this: 另一个更接近您原始建议的解决方案是这样的:

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;
    }
}

The downside to this (rather anti-pattern) approach is that you need to remember to create a constructor on your concrete class that calls super() ; 这种(相反的反模式)方法的缺点是,您需要记住在调用super()具体类上创建一个构造函数。

My congratulations for reading "Effective Java" and trying to put it into practice. 我祝贺您阅读了“有效的Java”并将其付诸实践。 It will bring more usability and clearness to your code. 它将为您的代码带来更多的可用性和清晰度。

Now, let's see: 现在,让我们看看:

1.In the first place, if your abstraction CentralPage just needs two Panel objects in the moment of construction, the simplest way would be a non-abstract class with two parameters in its constructor : 1.首先,如果您的抽象CentralPage在构造时仅需要两个Panel对象,则最简单的方法是在其构造函数中具有两个参数的非抽象类

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

2.If, appart from receiving parameters at construction, there is some behaviour which is not known to the CentralPage and it must be delegated to a third party at any time within the object's lifecycle (after the constructor ended), the proper pattern would be an abstract class with one abstract method for each required behaviour : 2.如果appart在构造时从接收参数开始,存在某些行为对于CentralPage是未知的,并且必须在对象的生命周期内的任何时候(在构造函数结束之后)委托给第三方,则正确的模式应为一个抽象类,每个必需的行为都有一个抽象方法

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

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

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

And, of corse, each non-abstract subclass must provide each required behaviour implemeting its corresponding method. 简而言之,每个非抽象子类都必须提供实现其相应方法的每个必需行为。

3.Static factory methods are aimed to non-abstract classes. 3.静态工厂方法针对非抽象类。 Its purpose is to decide if an object has to be created (maybe an existing object could be reused, like in the singleton pattern), and eventually to decide which class must be instantiated (maybe the owner class itself, or maybe some subclass). 其目的是确定是否必须创建对象 (可能像单例模式一样重用现有对象),并最终确定必须实例化哪个类 (可能是所有者类本身,或者可能是某些子类)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM