Frage

Ich bin sehr gespannt auf die Möglichkeit Unveränderlichkeit für Java Beans der Bereitstellung (von Bohnen hier I-Klassen mit einem leeren Konstruktor bedeuten Getter und Setter für Mitglieder bereitstellt). Offensichtlich sind diese Klassen nicht unveränderlich und wo sie zu Transportwerten aus der Datenschicht verwendet werden, dies scheint wie ein echtes Problem.

Ein Ansatz für dieses Problem ist in Stackoverflow hier erwähnten „Immutable Objektmuster in C #“ genannt, wo das Objekt einmal gefroren ist voll unterkellert. Ich habe einen alternativen Ansatz und würde wirklich gerne die Meinung der Menschen auf sie hören.

Das Muster besteht aus zwei Klassen Immutable und Mutable wo Mutable und Immutable sowohl eine Schnittstelle implementieren, die nicht mutiert Bean-Methoden zur Verfügung stellt.

Zum Beispiel

public interface DateBean {
    public Date getDate();
    public DateBean getImmutableInstance();
    public DateBean getMutableInstance();
}

public class ImmutableDate implements DateBean {
    private Date date;

ImmutableDate(Date date) {
    this.date = new Date(date.getTime());
}

public Date getDate() {
    return new Date(date.getTime());
}

    public DateBean getImmutableInstance() {
        return this;
    }

    public DateBean getMutableInstance() {
        MutableDate dateBean = new MutableDate();
        dateBean.setDate(getDate());
        return dateBean;
    }
}

public class MutableDate implements DateBean {
    private Date date;

public Date getDate() {
    return date;
}

public void setDate(Date date) {
    this.date = date;
}

public DateBean getImmutableInstance() {
    return new ImmutableDate(this.date);
}

    public DateBean getMutableInstance() {
        MutableDate dateBean = new MutableDate();
        dateBean.setDate(getDate());
        return dateBean;
    }
}

Dieser Ansatz ermöglicht die Bohne konstruiert wird mithilfe von Reflektion (nach den üblichen Konventionen) und erlaubt uns auch zu einer unveränderlichen Variante bei der nächsten Gelegenheit zu konvertieren. Leider gibt es eindeutig eine große Menge an vorformulierten pro Bohne.

Ich bin sehr daran interessiert, andere Menschen Ansatz in dieser Frage zu hören. (Ich entschuldige mich für keine gute Frage bereitstellt, die eher beantwortet werden können, als diskutiert:)

War es hilfreich?

Lösung

Ich denke, dass ich die Delegation Muster verwenden würde - eine ImmutableDate Klasse mit einem einzigen DateBean Mitglied machen, die im Konstruktor angegeben werden muss:

public class ImmutableDate implements DateBean
{
   private DateBean delegate;

   public ImmutableDate(DateBean d)
   {
      this.delegate = d;
   }

   public Date getDate()
   {
      return delegate.getDate();
   }
}

Wenn überhaupt muss ich Unveränderlichkeit zwingen, auf einem DateBean d, ich habe gerade neue ImmutableDate (d) darauf. Ich konnte klug gewesen und sorgte dafür, dass ich nicht die Delegierten delegieren haben, aber Sie bekommen die Idee. Das vermeidet das Problem eines Kunden versuchen, es in etwas wandelbar zu werfen. Dies ist ähnlich wie das JDK tut mit Collections.unmodifiableMap () usw. (in diesen Fällen jedoch haben die Mutation Funktionen noch umgesetzt werden, und codiert eine Laufzeitausnahme zu werfen. Viel einfacher, wenn Sie eine Basis-Schnittstelle haben, ohne die Mutatoren).

Wieder einmal ist es mühsam vorformulierten Code aber es ist die Art der Sache, dass eine gute IDE wie Eclipse können mit nur wenigen Mausklicks für Sie automatisch generieren.

Wenn es die Art von Sache, die Sie zu einer Menge von Domain-Objekten am Ende tun, mögen Sie vielleicht mit dynamischer Proxys prüfen, oder vielleicht sogar AOP. Es wäre relativ einfach sein, dann einen Proxy für jedes Objekt zu bauen, all get-Methoden zu delegieren, und Einfangen oder die Set-Methoden entsprechend zu ignorieren.

Andere Tipps

Einige Kommentare (nicht unbedingt Probleme):

  1. Die Date-Klasse ist selbst wandelbar, so dass Sie es richtig Unveränderlichkeit zu schützen kopieren, aber persönlich ziehe ich zu lange in dem Konstruktor konvertieren und ein neues Date (Longvalue) in dem Getter zurück.
  2. Sowohl Ihre getWhateverInstance () -Methoden DateBean zurück, die Gießen erforderlich machen wird, könnte es eine Idee sein, um die Schnittstelle zu ändern, anstatt den spezifischen Typ zurückzukehren.
  3. Nachdem alles gesagt, dass ich nur zwei Klassen bereit wäre, eine veränderbare und ein unveränderlich haben, eine gemeinsame (d bekommen nur) Schnittstelle teilen falls. Wenn Sie denken, es einen Kopierkonstruktor eine Menge Umwandlung hin und her, dann fügen Sie wird für beide Klassen.
  4. Ich ziehe es unveränderliche Klassen Felder zu erklären, endgültig die Compiler machen Unveränderlichkeit erzwingen auch.

z.

public interface DateBean {
    public Date getDate();
}

public class ImmutableDate implements DateBean {
    private final long date;

    ImmutableDate(long date) {
       this.date = date;
    }

    ImmutableDate(Date date) {
       this(date.getTime());
    }

    ImmutableDate(DateBean bean) {
       this(bean.getDate());
    }

    public Date getDate() {
         return new Date(date);
    }
}


public class MutableDate implements DateBean {
    private long date;

    MutableDate() {}

    MutableDate(long date) {
       this.date = date;
    }

    MutableDate(Date date) {
       this(date.getTime());
    }

    MutableDate(DateBean bean) {
       this(bean.getDate());
    }

    public Date getDate() {
        return new Date(date);
    }

    public void setDate(Date date) {
        this.date = date.getTime();
    }

}

Ich benutze Schnittstellen und Gießen der Veränderlichkeit der Bohnen zu steuern. Ich habe keinen Grund sehen zu meinen Domain-Objekten mit Methoden wie getImmutableInstance() und getMutableInstance() zu erschweren.

Warum nicht nur die Verwendung von Vererbung und Abstraktion machen? z.

public interface User{

  long getId();

  String getName();

  int getAge();

}

public interface MutableUser extends User{

  void setName(String name);

  void setAge(int age);

}

Hier ist, was der Kunde des Codes tun:

public void validateUser(User user){
  if(user.getName() == null) ...
}

public void updateUserAge(MutableUser user, int age){
  user.setAge(age);
}

Ist es Ihre Frage beantworten?

yc

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top