[JAVA] GoF design pattern from the problem 1. Generation

Design patterns are often described as "commonly encountered problems and their solutions." When designing, there is a problem first, and we look for a solution (pattern) for it. There are many articles summarized by pattern → problem → example, but I felt that there are few articles summarized by problem → pattern → example, so I wrote it. It's just in case I face the same problem myself, but I hope it helps. I would appreciate it if you could let me know if there is something wrong or something that can be improved. In addition, only the case where the GoF design pattern is applied when designing in Java is dealt with here. Also, please refer to here as we will not write a list of patterns or a description of each pattern.

  1. Generation
  2. Structure
  3. Behavior

Will be added at any time

: question: I want to give the constructor a descriptive name

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);

I don't think it's bad for a normal implementation, but there are cases where you want to be clear with and without proxies.

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);

It is easier to understand whether or not a proxy is used. (Especially when "not used")

: question: I want to return an instance according to the condition from the subclass without making the user aware

before

public class FooDateFilter extends FooFilter {}
public class FooNumberFilter extends FooFilter {}
public class FooStringFilter extends FooFilter {}
FooFilter filter = new FooStringFilter("foo");

It would be nice to have an interface that returns an instance of the subclass according to the 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");

Users no longer have to know what's in a subclass. Also, if one of the subclasses is abolished in the future and you want to use a new class, you can just modify the Factory and the user will not be aware of it.

: question: I want to set one by one because there are many fields, but I want to make it immutable after setting

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);
  }

Below color,Similar method for backgroundColor
}
new FooWindow()
  .withWidth(100)
  .withHeight(200)
  .withColor(color)
  .withBackgroundColor(backgroundColor);

It's useless to instantiate every time. If mutable is acceptable, you can substitute it in your own field with withWidth. (It's not a GoF pattern, but it's a pattern called Fluent Setter or 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;
    }

Below color,Similar method for 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();

Instance generation has been suppressed. If the number of fields is four as in this example, I think that there is still no problem with the constructor, but as the number increases further, it becomes difficult to know what number argument represents what. In such cases, consider the Builder pattern.

Recommended Posts

GoF design pattern from the problem 1. Generation
GoF design pattern from the problem 2. Structure
GoF design pattern from the problem 3. Behavior
GoF java design pattern rough summary
Learn the design pattern "Builder" in Python
Learn the design pattern "Flyweight" in Python
Learn the design pattern "Observer" in Python
Learn the design pattern "Memento" in Python
Learn the design pattern "Proxy" in Python
Learn the design pattern "Visitor" in Python
Learn the design pattern "Bridge" in Python
Learn the design pattern "Mediator" in Python
Learn the design pattern "Decorator" in Python
Learn the design pattern "Iterator" in Python
Learn the design pattern "Strategy" in Python
Learn the design pattern "Composite" in Python
Learn the design pattern "Singleton" with Python
Learn the design pattern "State" in Python
Learn the design pattern "Adapter" in Python
Learn the design pattern "Facade" with Python
Design Pattern #Builder
Learn the design pattern "Abstract Factory" in Python
Design Pattern #Decorator
Learn the design pattern "Template Method" in Python
Design Pattern #Observer
Learn the design pattern "Factory Method" in Python
Design Pattern #Facade
Design Pattern #Strategy
Design Pattern #Singleton
Design Pattern #Proxy
Learn the design pattern "Chain of Responsibility" in Python
Design Pattern #Factory Method
Logistics network design problem
Design Pattern #Template Method
About the Visitor pattern
Examine the dual problem
GoF design pattern is just an "introduction of abstraction layer"
Ambulance placement problem --From the October issue of the OR magazine