Im letzten Jahr konnte ich endlich objektorientierten Code schreiben. Ich habe 1995 zum ersten Mal etwas über Objektorientierung gelernt, also hat es mehr als 20 Jahre gedauert.
Der Grund, warum ich objektorientierten Code schreiben konnte Dies liegt daran, dass ich versucht habe, unter Berücksichtigung des Wertobjekts zu schreiben.
Die einfachste Definition ist die Übersetzung des Artikels von Dr. Martin Fowler (Value Object) [^ 1].
Im Fall von Java ist es gut, die folgenden zwei zu erfüllen. Es ist nicht direkt verwandt, implementiert aber auch toString ().
Implementieren wir beispielsweise eine [java.time.Year] [] -ähnliche Klasse, MyYear. Es ist mühsam, equals () und hashCode () richtig zu implementieren, daher überlasse ich es IDE (IntelliJ IDEA).
public final class MyYear {
private final int year;
private MyYear(int year) {
this.year = year;
}
public static MyYear of(int year) {
return new MyYear(year);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyYear myYear = (MyYear) o;
return year == myYear.year;
}
@Override
public int hashCode() {
return year;
}
@Override
public String toString() {
return "MyYear{" +
"year=" + year +
'}';
}
}
Sie können Apache Commons Lang auch für die Implementierung verwenden. Es verwendet Reflexion, aber die Beschreibung ist einfach. (Einige APIs verwenden keine Reflektion.)
Der Grund, warum SHORT_PREFIX_STYLE für toString () verwendet wird, ist Sie benötigen keinen Hash-Code für das Objekt, sondern nur den Wert des Feldes.
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
public final class MyYear {
private final int year;
private MyYear(int year) {
this.year = year;
}
public static MyYear of(int year) {
return new MyYear(year);
}
@Override
public boolean equals(Object o) {
return EqualsBuilder.reflectionEquals(this, o);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
Derzeit gibt es drei Hauptvorteile.
Wenn Sie beispielsweise eine Methode möchten, die nächstes Jahr zurückgegeben wird, können Sie sie in der MyYear-Methode implementieren. Die Logik ist auf eine Klasse konzentriert, was das Ändern erleichtert.
public MyYear nextYear() {
return new MyYear(this.year + 1);
}
Es kann wie folgt als Schlüssel verwendet werden.
import java.util.HashMap;
public final class Main {
public static void main(String[] args) {
var myMap = new HashMap<>();
myMap.put(MyYear.of(2018), "2018");
System.out.println(myMap.get(MyYear.of(2018))); // =>2018. gleich()Null, wenn es keine gibt
}
}
Es ist in Ordnung, Objekte normal zu vergleichen. Wenn Sie nicht gleich () definieren, müssen Sie einen Getter definieren, um den Wert des Feldes zu erhalten.
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public final class MyYearTest {
@Test
public void testMyYearNext() {
MyYear now = MyYear.of(2018);
MyYear next = MyYear.of(2019);
assertThat(now.nextYear()).isEqualTo(next);
}
}
Objektorientierte Definitionen umfassen häufig "Kapselung", "Vererbung" und "Polymorphismus". Abgesehen vom Polymorphismus passen die beiden anderen nicht ganz zusammen.
Encapsulation ist kein Setter / Getter, aber ich konnte nicht herausfinden, was ich schreiben soll, ob Vererbung wirklich notwendig ist und so weiter.
Da ich jedoch angefangen habe, Wertobjekte richtig zu erstellen, zögere ich weniger und kann Code schreiben, der leicht zu verstehen ist. Die einzige Schwäche ist "es ist ein Schmerz, zuerst zu schreiben", aber ich denke, das sind notwendige Kosten.
Eigentlich denke ich, dass domänengesteuertes Design leichter zu verstehen ist als objektorientiert, aber ich dachte, dass es zu ausgefallen ist, also habe ich mich vorerst auf Value Object konzentriert.
Wenn Sie es ernsthafter machen wollen (?), Denke ich, dass der folgende Aufsatz, auch "OO Code Training Gibbs" genannt, hilfreich sein wird. Dies ist jedoch ziemlich schwierig. Ich kann nicht ... (ヽ ´ω`)
[^ 1]: Es wurden verschiedene Ergänzungen zum Originaltext vorgenommen (ValueObject), aber diesmal handelt es sich nur um eine Definition, daher werde ich die alte Beschreibung verwenden. [^ 2]: Selbst wenn final hinzugefügt wird, kann nicht gesagt werden, dass es unveränderlich ist, wenn List usw. enthalten ist, aber die Erklärung wird hier weggelassen. [java.time.Year]: https://docs.oracle.com/javase/jp/8/docs/api/java/time/Year.html
Recommended Posts