2017-09-19 2 views
1

Ich mache eine Coin-Klasse mit einer statischen Arraylist, die jede Instanz der erstellten Klasse speichert, aber ich muss diese Liste mit einer ersten Instanz initiieren, und ich habe nicht herausgefunden, wie machen Sie es, ohne es zweimal hinzuzufügen (wegen eines überflüssigen Codes), irgendwelche Vorschläge?statische Arraylist mit Instanzen der Klasse mit Initialwerten

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

* statische Arraylist, die jede Instanz speichert * nicht sicher, was Ihre – Ravi

+2

zu tun versuchen Denkt bitte halten, dass dieses Muster von Natur aus fad unsicher ist (dh ist, man kann grundsätzlich keinen thread-sicheren Code damit machen), also ist es eine schlechte Angewohnheit, hineinzugehen. Ein besserer Ansatz wäre ein privater Konstruktor und eine statische Factory-Methode, die diesen Konstruktor aufruft und dann die Instanz zu "coins" hinzufügt. – yshavit

+0

Besser wäre es, eine CoinFactory-Klasse zu haben, die Coin-Instanzen erstellt (und zurückgibt) und sie selbst hinzufügt. Ihre aktuelle Lösung ist nicht Thread-sicher und das ist nur ein Nachteil. – DodgyCodeException

Antwort

0

Sie könnten Ihre Anwendung auch mit Best-Practice-Mustern gestalten. Sie möchten eine Registrierung aller erstellten Münzen führen. Dies wird am besten außerhalb der Münzklasse selbst gehalten. Sie könnten eine Klasse haben, die die Erstellung von Münzen verwaltet und eine Liste der von Ihnen erstellten Münzen führt. Die Coin-Klasse selbst kann eine Schnittstelle sein, wenn Sie möchten, so dass Sie sicherstellen, dass sie nicht anders als durch die CoinFactory erstellt werden kann.

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

Und die Münze Fabrik Klasse:

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

Wenn Sie darauf bestehen, überhaupt wandelbar statische Variablen mit - es ist in der Regel keine gute Idee, Dinge wie diese überhaupt zu tun - Sie

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

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

tun könnte ... was die Adds Element zur Liste sofort.

+0

was ist dann eine bessere Idee? –

+3

Haben Sie eine tatsächliche Klasse, die alle Ihre Münzen speichert. Machen Sie es nicht mit dem Konstruktor verbunden, listen Sie alle explizit auf. –

+0

richtig, ich sehe, danke! –

1

Was hält Sie davon ab, Ihre Liste in ihrer Deklaration zu initialisieren und dann jede Instanz der Liste im Konstruktor hinzuzufügen?

+2

Das macht das OP, aber was sie wollen ist, dass eine Münze (die "Pesos chilenos") "automatisch" hinzugefügt wird, ohne dass der Benutzer dieser Klasse sie manuell instanziieren muss. – yshavit

Verwandte Themen