2 votes

Usine abstraite en Java - Comment l'étendre ?

J'utilise la bibliothèque Java, core , avec AbstractFactory responsable des composants de l'interface utilisateur. MyApplication utilise le noyau et personnalise l'interface utilisateur. C'est pourquoi, lors du démarrage de MyApplication, je définis MyFactory comme une instance d'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())
}

Mon problème est que je dois créer, par exemple, JList dans MyApplication, mais je ne peux pas ajouter public JList createJList() dans AbstractFactory, car je ne peux pas modifier la bibliothèque de base.

Que dois-je faire ?

Premier cas : Toujours appeler MyFactory.getMyFactoryInstance() dans MyApplication, nouveau champ statique.

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

Deuxième cas : Toujours appeler MyFactory.getMyFactoryInstance() dans MyApplication, utiliser le cast

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

Troisième cas : Utiliser deux usines. Pour JButtons et JLabels, utilisez AbstractFactory, pour JList utilisez SomeOtherFactory.

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

Quatrième cas : Quelque chose de mieux ? J'ai l'impression d'avoir oublié quelque chose.

1voto

GordyD Points 2722

Je créerais une sous-classe abstraite de AbstractFactory qui spécifie le createJList() et écrase la méthode getInstance() qui renvoie le nouveau type de classe abstraite. Vous pouvez alors mettre en œuvre la logique dans votre classe MyFactory et vous en tenir à la méthode principe de programmation vers des interfaces (en l'occurrence, des abstractions), et non vers des implémentations ¡!

Exemple de code :

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

L'exemple ci-dessus utilise instanciation paresseuse Ce qui est très bien si le code n'est pas toujours utilisé et s'il n'est pas utilisé dans une application à plusieurs fils. S'il est toutefois utilisé dans une application multithread, j'utiliserais l'implémentation suivante de MyFactory qui utilise verrouillage doublement vérifié pour gérer plusieurs fils de discussion.

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

Quelle que soit la solution retenue, l'utilisation restera la même.

Utilisation :

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

0voto

Bohemian Points 134107

Puisque vous avez besoin de différentes usines pour construire différentes choses, avez-vous envisagé d'incorporer des génériques ?

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

Il suffit d'avoir une usine typée pour chaque type de chose que vous devez créer. Par exemple :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X