2017-09-19 1 views
1

En créant une classe Coin avec une liste statique qui stocke toutes les instances de la classe créée, j'ai besoin d'initialiser cette liste avec une instance initiale, et je n'ai pas compris comment le faire sans l'ajouter deux fois (à cause d'un code redondant), des suggestions?arraylist statique avec des instances de classe avec des valeurs initiales

public class Coin { 
    private static ArrayList<String> coinNames = new ArrayList<>(); 
    private static ArrayList<String> coinAbbreviations = new ArrayList<>(Arrays.asList("CLP")); 
    private static ArrayList<Coin> coins = 
      new ArrayList<>(Arrays.asList(new Coin("Pesos chilenos", "CLP", 1f, "CLP"))); 
    private static HashMap<String,Float> exchangeRates; 
    private String coinName; 
    private String coinAbbreviation; 
    private Float coinValue; 
    private String unit; 


    public Coin(String coinName, String coinAbbreviation, Float coinValue, String unit) { 
     assert !coinAbbreviations.contains(coinAbbreviation) : "Coin abbreviation already used"; 
     assert coinAbbreviations.contains(unit) : "Coin unit non existent."; 
     assert !coinNames.contains(coinName) : "Coin name already used."; 
     this.coinName = coinName; 
     this.coinAbbreviation = coinAbbreviation; 
     this.coinValue = coinValue; 
     this.unit = unit; 

     coins.add(this); 
    } 
} 
+1

* arraylist statique qui stocke tous les cas * ne sais pas ce que sont vous essayez de faire – Ravi

+2

S'il vous plaît garder à l'esprit que ce modèle est thread-dangereux en soi (ce est, vous ne pouvez fondamentalement jamais faire de code thread-safe avec elle), donc c'est une mauvaise habitude à prendre. Une meilleure approche serait un constructeur privé, et une méthode d'usine statique qui appelle ce constructeur, puis ajoute l'instance à 'pièces de monnaie». – yshavit

+0

Mieux serait d'avoir une classe CoinFactory qui crée (et renvoie) des instances Coin et les ajoute à elle-même. Votre solution actuelle n'est pas sûre pour les threads et c'est juste un inconvénient. – DodgyCodeException

Répondre

0

Vous pouvez également concevoir votre application en utilisant des modèles de meilleures pratiques. Vous voulez garder un registre de toutes les pièces créées. C'est mieux gardé en dehors de la classe Coin lui-même. Vous pourriez avoir une classe qui gère la création de pièces de monnaie et conserve une liste de ceux qu'elle a créés. La classe Coin elle-même peut être une interface, si vous voulez, de cette façon vous vous assurez qu'elle ne peut être créée que par CoinFactory.

public interface Coin { 
    String name(); 
    String abbreviation(); 
    BigDecimal value(); 
    String unit(); 
} 

Et la classe usine Coin:

public class CoinFactory { 

    // Concrete coin is an internal implementation class whose details don't 
    // need to be known outside of the CoinFactory class. 
    // Users just see it as interface Coin. 
    private static class ConcreteCoin implements Coin { 
     private final String name; 
     private final String abbreviation; 
     private final BigDecimal value; 
     private final String unit; 

     ConcreteCoin(String name, String abbreviation, BigDecimal value, String unit) { 
      this.abbreviation = abbreviation; 
      this.name = name; 
      this.value = value; 
      this.unit = unit; 
     } 

     public String name() { return name; } 
     public String abbreviation() { return abbreviation; } 
     public BigDecimal value() { return value; } 
     public String unit() { return unit; } 
    } 

    // Sets for enforcing uniqueness of names and abbreviations 
    private Set<String> names = new HashSet<>(); 
    private Set<String> abbreviations = new HashSet<>(); 

    // All coins must have one of the following ISO currency codes as the 'unit' field. 
    private final Set<String> allIsoCurrencyCodes = 
      Set.of("CLP", "GBP", "EUR", "CAD", "USD", "XXX" /* , ... */); 

    private List<Coin> allCoins = new ArrayList<>(
      List.of(createCoin("Pesos chilenos", "CLP", BigDecimal.ONE, "CLP"))); 

    private List<Coin> unmodifiableListOfAllCoins = 
      Collections.unmodifiableList(allCoins); 


    public Coin createCoin(String name, String abbreviation, BigDecimal value, String unit) { 
     if (!names.add(name)) 
      throw new IllegalArgumentException("Name already exists: " + name); 
     if (!abbreviations.add(abbreviation)) 
      throw new IllegalArgumentException("Abbreviation already exists: " + abbreviation); 
     if (!allIsoCurrencyCodes.contains(unit)) 
      throw new IllegalArgumentException("Coin unit is not a recognised ISO currency code: " + unit); 

     Coin coin = new ConcreteCoin(name, abbreviation, value, unit); 
     allCoins.add(coin); 
     return coin; 
    } 

    public Collection<Coin> allCoins() { 
     return unmodifiableListOfAllCoins; 
    } 
} 
5

Si vous insistez pour avoir des variables statiques mutables du tout - il est généralement pas une bonne idée de faire des choses comme ça du tout - vous pouvez faire

private static ArrayList<Coin> coins = 
     new ArrayList<>(); 

static { 
    new Coin("Pesos chilenos", "CLP", 1f, "CLP"); 
} 

... qui ajoute la élément à la liste immédiatement. Qu'est-ce qui vous empêche d'initialiser votre liste dans sa déclaration, puis d'ajouter simplement chaque instance à la liste dans le constructeur?

+0

quelle est alors une meilleure idée? –

+3

Avoir une classe réelle qui stocke toutes les pièces que vous faites. Ne le faites pas lié au constructeur, listez-les tous explicitement. –

+0

droite, je vois, merci! –

1

+2

C'est ce que fait l'OP, mais ce qu'il veut, c'est qu'un Coin (le "Pesos chilenos") soit ajouté automatiquement, sans que l'utilisateur de cette classe doive l'instancier manuellement. – yshavit