11
votes

Faire des propriétés Java disponibles à travers les classes?

J'ai choisi de prendre un fichier de propriétés pour la personnalisation de certains paramètres. J'utilise le code suivant pour créer un objet de propriétés disponible dans une classe

Properties defaultProps = new Properties();
    try {
        FileInputStream in = new FileInputStream("custom.properties");
        defaultProps.load(in);
        in.close();
    } catch (Exception e) {
        e.printStackTrace();
    }


1 commentaires

8 Réponses :


14
votes

Une fois que vous avez initialisé defaultProps , vous pouvez créer son contenu disponible pour d'autres objets de votre application. Via une méthode d'accesseur statique public, par exemple: xxx

Il s'agit de l'approche la plus simple, mais elle crée une dépendance supplémentaire qui rend le test de l'unité plus difficile (sauf si vous fournissez une méthode dans config Pour définir un objet de la propriété simulée pour le test de l'unité).

une alternative consiste à injecter defaultProps (ou valeurs de configuration individuelles de celle-ci) dans chaque objet qui en a besoin. Cependant, cela peut signifier que vous devez ajouter des paramètres supplémentaires à de nombreuses méthodes si vos hiérarchies d'appels sont profondes.


11 commentaires

Je n'aime pas cette solution. Faire la méthode non statique et la création d'un singleton le rend beaucoup plus flexible et ne coûte rien.


@maaArtinus: Comment appliquer exactement le modèle singleton plus flexible? Ne le déroulez-vous pas avec le modèle d'usine abstrait?


@maaArtinus, comment un singleton ferait-il cela plus flexible? Notez que pratiquement cela est déjà un singleton (c'est un objet global unique, avec tous ses bagages de dépendance), vient de cacher une interface.


Eh bien, je considère un singleton seulement un réel singleton quand il a été paresseusement chargé sur le premier accès. C'est aussi l'intention de tout le singleton. Sinon, il y a juste des moyens de «créer simplement un» modèle.


@Ballusc, je n'ai jamais entendu dire que le chargement paresseux serait une condition d'être un "réel" singleton (bien que sûrement, il soit souvent utilisé en conjonction). Quoi qu'il en soit, il serait assez trivial de modifier l'exemple ci-dessus pour charger les propriétés paresseusement. Mais je pense que l'OP n'aurait pas besoin de confondre des détails et des astuces encore plus techniques :-)


D'accord, un vrai singleton est aussi flexible que l'utilisation de méthodes statiques. Cependant, il est beaucoup plus facile de se transformer en quelque chose de mieux. Vous pouvez le faire en petites étapes en remplaçant l'utilisation de MySingleton.getinstance () en faisant passer l'objet comme par exemple. paramètre cors. De cette façon, j'ai une fois éliminé quelques singletons et terminés par de belles di. Lorsque vous commencez par des méthodes statiques, vous pouvez le convertir en un singleton d'abord, puis continuer comme ci-dessus.


@maaArtinus, vous pouvez faire la même chose directement avec une méthode statique. Si vous préférez personnellement des singletons, cela ne me dérange pas un peu, mais techniquement, il n'y a pas de différence réelle.


Je ne peux pas! Je ne peux pas remplacer tous les appels à static config.getsomething dans une classe par méthode non statique des appels config.getsomething et laissez-les seul ailleurs. Sauf si j'écris une nouvelle classe / méthode. Le moyen le plus simple de faire de telles petites étapes vers DI est de commencer avec la transformation en singleton. Cela dit, les singletons sont aussi diaboliques. Ou pouvez-vous me montrer pourquoi je me trompe?


@maaArtinus, je ne vois vraiment pas la différence fondamentale entre a) éliminer un appel à config.getinstance (). GetProperty ("FOO") En injectant un paramètre de méthode String FOOPARAMÈTRE , et b) éliminer un appel à config.geproperty ("foo") à l'aide du même paramètre de méthode.


D'accord maintenant je comprend. Cependant, vous ne pouvez pas injecter une instance de config et l'utiliser, qui est une étape moins douloureuse. En fait, pour des configurations que l'injection directe de la faplaamètre soit meilleure (loi de Demeter), mais normalement, vous ne voulez pas désassembler votre classe.


Pour éviter votre problème de dépendance, envisagez d'implémenter une injection de dépendance à l'aide d'un motif de méthode d'usine. Voir cette réponse pour un exemple Stackoverflow.com/a/27724421/2048879



0
votes

Il y a trop peu d'informations pour déterminer quelle serait la meilleure façon de gérer cela. Vous voudrez peut-être l'exposer à l'aide d'un accesseur ou de le transmettre à chaque classe qui l'exige. Sinon, vous pouvez extraire les propriétés que chaque classe a besoin et transmettez leurs valeurs dans le constructeur de la classe.


0 commentaires

0
votes

Chargez les propriétés une fois en utilisant et stockez les propriétés quelque part surprenant que d'autres classes peuvent tirer de. Si c'est une classe myProperties qui fait référence à une variable statique quelque part qui convient bien.


0 commentaires

0
votes

Ceci est un cas particulier de faire quoi que ce soit disponible dans le monde. L'utilisation de méthodes statiques est assez mauvaise. Une solution meilleure mais mauvaise utilise le sigleton motif. Le test est le plus grand problème ici. IMHO, le meilleur moyen consiste à utiliser Injection de dépendance , bien que cela puisse être une overcelle pour les petites applications. < / p>


0 commentaires

3
votes

Si vous n'avez besoin que d'une instance de votre classe de propriétés, vous pouvez utiliser le singleton (anti?) - modèle .

Cela ressemblerait à une classe comme celle-ci: xxx


2 commentaires

"Ceci.Load (dans);" doit être "instance.load (dans);"


@ficedek fixe (quelle vieille réponse de la mienne!)



0
votes

Étant donné que ces informations sont statiques dans toutes les instances, je vous recommande d'implémenter la classe code> code> comme un singleton . En utilisant le statique code> bloc d'initialisation Méthode, vous pouvez le charger automatiquement du fichier lorsque le programme démarre.

public class Properties {
  static {
    try {
      FileInputStream in = new FileInputStream("custom.properties");
      load(in);
      in.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  protected static void load(FileInputStream in) {
    // existing load functionality here
  }
}


0 commentaires

1
votes

Pourquoi ne pas utiliser une ressource statiqueBundle?

static final ResourceBundle myResources = 
          ResourceBundle.getBundle("MyResources", currentLocale);


0 commentaires

0
votes

plutôt que de charger des propriétés dans chaque classe. Chargez-le quelque part autour de la main () et transmettez-le à d'autres classes via leurs constructeurs.

Ne les partage pas globalement. - difficile à tester - contre l'abstraction (accès global, DAO peut accéder aux paramètres de l'utilisateur. Il ne faut pas empêcher en passant uniquement ce qu'il a besoin .. pas tout) - Les classes mentent ce dont ils ont besoin


0 commentaires