2016-08-21 17 views
0

У меня есть «стандарт» JPanel с двумя панелями внутри. Я пытался создать класс шаблонов, а затем расширить его и реализовать контент. Вопрос в том, каким будет его реализация.Как создать абстрактный класс со статическим методом фабрики?

Код, приведенный ниже, является тем, что я пытаюсь заставить его работать, но я только начал читать эффективную книгу 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); 

} 

Не стесняйтесь спрашивать, нужна ли вам дополнительная информация о других частях кода.

+0

Что [* проблема *] (http://meta.stackoverflow.com/q/66377/163188) вы пытаетесь решить – trashgod

+0

Я думаю, у меня есть абстрактный класс со статическим заводским методом по умолчанию, но это невозможно добавить статические методы в абстрактные классы. Поэтому я пытаюсь найти стандартную работу. Лучше? –

+0

Основная идея предоставления статических заводских методов вместо конструкторов - это скрытие реализации. Реализации скрыты где-то в частных или анонимных классах. Вы приближаетесь, больше похожи на абстрактные фабричные методы. Вы должны предоставить общий заводский интерфейс, который затем можно использовать для настройки ваших панелей. Тем не менее, вы по-прежнему можете предоставлять «стандартные» реализации заводских методов в качестве статических методов, если это необходимо. – kaetzacoatl

ответ

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();

+0

И как мне «называть» это «класс»? (класс, который реализует UpDown) 'static JPanel getInstance() { \t return CentralPage.getInstance (this); } '? –

+0

Это будет невозможно, потому что 'this' не имеет смысла в методе' static'. Но почему вы хотите построить родительский элемент в дочернем классе? У вас может быть больше возможностей (например, ваше приложение пользовательского интерфейса), где вы бы назвали 'JPanel mainPanel = CentralPage.getInstance (новый UpDown() {/ * реализовать два метода * /}); – Deroude

0

Поздравляю вас за чтение «Эффективной Java» и попытку воплотить его в жизнь. Это принесет вам больше удобства и ясности.

Теперь, давайте посмотрим:

1.В первую очередь, если ваша абстракция CentralPage просто нужно два объекта Panel в момент строительства, самым простым способом было бы не-абстрактный класс с двумя параметрами его конструктор:

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

2.Если, appart от получения параметров при конструировании, существует некоторое поведение, которое неизвестно CentralPage и оно должно быть делегировано третьей стороне в любое время в жизненном цикле объекта (после завершения конструктора), правильный шаблон будет a абстрактный класс с одним абстрактным методом для каждого требуемого поведения:

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

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

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

И, Corse, каждый неабстрактный подкласс должен обеспечить требуемое поведение каждого implemeting его соответствующий метод.

3. Статические методы завода направлены на не-абстрактные классы. Его цель состоит в том, чтобы решить , если объект должен быть создан (возможно, существующий объект можно было бы повторно использовать, например, в шаблоне singleton) и в конечном итоге решить , какой класс должен быть создан (может быть, сам класс владельца, некоторый подкласс).