Entwurfsmuster werden häufig als "häufig auftretende Probleme und ihre Lösungen" beschrieben. Beim Entwerfen gibt es zuerst ein Problem, und wir suchen nach einer Lösung (einem Muster) dafür. Es gibt viele Artikel, die nach Muster → Problem → Beispiel zusammengefasst sind, aber ich hatte das Gefühl, dass es nur wenige Artikel gibt, die nach Problem → Muster → Beispiel zusammengefasst sind, also habe ich es geschrieben. Es ist nur für den Fall, dass ich selbst vor dem gleichen Problem stehe, aber ich hoffe, es hilft. Ich würde mich freuen, wenn Sie mich wissen lassen könnten, ob etwas nicht stimmt oder verbessert werden kann. Außerdem wird hier nur der Fall behandelt, in dem das GoF-Entwurfsmuster beim Entwerfen mit Java angewendet wird. Lesen Sie auch hier, da wir keine Liste von Mustern oder eine Beschreibung jedes Musters schreiben.
Wird jederzeit hinzugefügt
before
public class FooClient {
private final String url;
private final String proxyHost;
private final int proxyPort;
public FooClient(String url) {
this.url = url;
this.proxyHost = null;
this.proxyPort = -1;
}
public FooClient(String url, String proxyHost, int proxyPort) {
this.url = url;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
}
}
new FooClient(url);
new FooClient(url, proxyHost, proxyPort);
Ich denke nicht, dass es für eine normale Implementierung schlecht ist, aber es gibt Fälle, in denen Sie mit und ohne Proxy klar sein möchten.
after :bulb: Factory Method
public class FooClient {
private final String url;
private final String proxyHost;
private final int proxyPort;
private FooClient(String url, String proxyHost, int proxyPort) {
this.url = url;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
}
public static FooClient withoutProxy(String url) {
return new FooClient(url, null, -1);
}
public static FooClient withProxy(String url, String proxyHost, int proxyPort) {
return new FooClient(url, proxyHost, proxyPort);
}
}
FooClient.withoutProxy(url);
FooClient.withProxy(url, proxyHost, proxyPort);
Es ist einfacher zu verstehen, ob ein Proxy verwendet wird oder nicht. (Besonders wenn "nicht verwendet")
before
public class FooDateFilter extends FooFilter {}
public class FooNumberFilter extends FooFilter {}
public class FooStringFilter extends FooFilter {}
FooFilter filter = new FooStringFilter("foo");
Es wäre schön, eine Schnittstelle zu haben, die eine Instanz der Unterklasse gemäß dem Argument zurückgibt.
after :bulb: FactoryMethod
public class FooDateFilter extends FooFilter {}
public class FooNumberFilter extends FooFilter {}
public class FooStringFilter extends FooFilter {}
public class FooFilterFactory {
private FooFilterFactory() {}
public static FooFilter create(Date date) {
return new FooDateFilter(date);
}
public static FooFilter create(Number number) {
return new FooNumberFilter(number);
}
public static FooFilter create(String string) {
return new FooStringFilter(string);
}
}
FooFilter filter = FooFilterFactory.create("foo");
Der Benutzer muss nicht mehr wissen, was sich in der Unterklasse befindet. Wenn eine der Unterklassen in Zukunft abgeschafft wird und Sie eine neue Klasse verwenden möchten, können Sie einfach die Factory ändern, und der Benutzer wird sich dessen nicht bewusst sein.
before
public class FooWindow {
private final int width;
private final int height;
private final FooColor color;
private final FooColor backgroundColor;
public FooWindow() {
this.width = 0;
this.height = 0;
this.color = null;
this.backgroundColor = null;
}
public FooWindow(int width, int height, FooColor color, FooColor backgroundColor) {
this.width = width;
this.height = height;
this.color = color;
this.backgroundColor = backgroundColor;
}
public FooWindow withWidth(int width) {
return new FooWindow(width, this.height, this.color, this.backgroundColor);
}
public FooWindow withHeight(int height) {
return new FooWindow(this.width, height, this.color, this.backgroundColor);
}
Unter Farbe,Ähnliche Methode für backgroundColor
}
new FooWindow()
.withWidth(100)
.withHeight(200)
.withColor(color)
.withBackgroundColor(backgroundColor);
Es ist sinnlos, jedes Mal eine Instanz zu erstellen. Wenn veränderlich akzeptabel ist, können Sie es in Ihrem eigenen Feld durch withWidth ersetzen. (Es ist kein GoF-Muster, aber es ist ein Muster namens Fluent Setter oder Wither)
after :bulb: Builder
public class FooWindow {
private final int width;
private final int height;
private final FooColor color;
private final FooColor backgroundColor;
public FooWindow(int width, int height, FooColor color, FooColor backgroundColor) {
this.width = width;
this.height = height;
this.color = color;
this.backgroundColor = backgroundColor;
}
public static class FooWindowBuilder {
private int width;
private int height;
private FooColor color;
private FooColor backgroundColor;
public FooWindowBuilder withWidth(int width) {
this.width = width;
return this;
}
public FooWindowBuilder withHeight(int height) {
this.height = height;
return this;
}
Unter Farbe,Ähnliche Methode für backgroundColor
public FooWindow build() {
return new FooWindow(this.width, this.height, this.color, this.backgroundColor);
}
}
}
new FooWindowBuilder()
.withWidth(100)
.withHeight(200)
.withColor(color)
.withBackgroundColor(backgroundColor)
.build();
Die Instanzgenerierung wurde unterdrückt. Wenn die Anzahl der Felder wie in diesem Beispiel vier beträgt, gibt es meines Erachtens immer noch kein Problem mit dem Konstruktor, aber wenn die Anzahl weiter zunimmt, wird es schwierig zu wissen, welches Zahlenargument was darstellt. Berücksichtigen Sie in solchen Fällen das Builder-Muster.
Recommended Posts