Les modèles de conception sont souvent décrits comme «des problèmes fréquemment rencontrés et leurs solutions». Lors de la conception, il y a d'abord un problème et nous cherchons une solution (modèle) pour cela. Il existe de nombreux articles résumés par modèle → problème → exemple, mais j'ai senti qu'il y avait peu d'articles résumés par problème → modèle → exemple, alors je l'ai écrit. C'est juste au cas où je ferais face au même problème moi-même, mais j'espère que cela aide. Je vous serais reconnaissant si vous pouviez me faire savoir s'il y a quelque chose qui ne va pas ou quelque chose qui peut être amélioré. De plus, seul le cas où le modèle de conception GoF est appliqué lors de la conception avec Java est traité ici. Veuillez également vous référer à ici car nous n'écrirons pas une liste de modèles ou une description de chaque modèle.
Sera ajouté à tout moment
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);
Je ne pense pas que ce soit mauvais pour une implémentation normale, mais il y a des cas où vous voulez être clair avec et sans proxy.
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);
Il est plus facile de comprendre si un proxy est utilisé ou non. (Surtout quand "non utilisé")
before
public class FooDateFilter extends FooFilter {}
public class FooNumberFilter extends FooFilter {}
public class FooStringFilter extends FooFilter {}
FooFilter filter = new FooStringFilter("foo");
Ce serait bien d'avoir une interface qui renvoie une instance de la sous-classe en fonction de l'argument.
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");
L'utilisateur n'a plus besoin de savoir ce qu'il y a dans la sous-classe. De plus, si l'une des sous-classes est abolie à l'avenir et que vous souhaitez utiliser une nouvelle classe, vous pouvez simplement modifier la fabrique et l'utilisateur n'en sera pas conscient.
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);
}
Sous la couleur,Méthode similaire pour backgroundColor
}
new FooWindow()
.withWidth(100)
.withHeight(200)
.withColor(color)
.withBackgroundColor(backgroundColor);
Il est inutile de créer une instance à chaque fois. Si mutable est acceptable, vous pouvez le remplacer dans votre propre champ par withWidth. (Ce n'est pas un modèle GoF, mais c'est un modèle appelé Fluent Setter ou 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;
}
Sous la couleur,Méthode similaire pour 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();
La génération d'instance a été supprimée. Si le nombre de champs est de quatre comme dans cet exemple, je pense qu'il n'y a toujours pas de problème avec le constructeur, mais à mesure que le nombre augmente encore, il devient difficile de savoir quel argument numérique représente quoi. Dans de tels cas, considérez le modèle Builder.
Recommended Posts