This is the 8th day of my participation in the August More text Challenge. For details, see: August More Text Challenge


1. Multi-platform software design

To develop a piece of software, the requirement is to support multiple platforms, and the code should be reused as much as possible. The architecture looks and functions the same regardless of the platform, but different components implement different code on different platforms. Suppose the software is simple and consists of only three parts: a button, a text box, and a gorgeous chart. First, the component interface is abstracted, and the features and functions of the component are defined.

public interface Button {

	// The button can be clicked
	void click(a);
}

public interface Text {

	// The text can be displayed
	void display(a);
}

public interface Chart {

	// The graph is cool
	void show(a);
}
Copy the code

Assuming that only Windows and Linux systems are currently supported, you need to write different implementation code for each platform.

class WindowsButton implements Button{

	@Override
	public void click(a) {
		System.out.println("Windows button clicked"); }}class LinuxButton implements Button{

	@Override
	public void click(a) {
		System.out.println("Linux button clicked"); }}class WindowsText implements Text{

	@Override
	public void display(a) {
		System.out.println("Windows Text Box Display"); }}class LinuxText implements Text{

	@Override
	public void display(a) {
		System.out.println("Linux Text box display"); }}class WindowsChart implements Chart{

	@Override
	public void show(a) {
		System.out.println("Windows Chart Display"); }}class LinuxChart implements Chart{

	@Override
	public void show(a) {
		System.out.println("Linux Chart Presentation"); }}Copy the code

The software class is composed of Button, Text and Chart.

/ / software
public class Application {
	private Button button;
	private Text text;
	private Chart chart;

	public void buttonClick(a){
		button.click();
	}

	public void textDisplay(a){
		text.display();
	}

	public void showChart(a){ chart.show(); }}Copy the code

Now that the software and component classes are defined, how do you assemble these components? Manual new out and then set? How do you know if I need a Windows component or a Linux component? What would you do if you were to develop one for the Mac?

Define a factory interface, specify which components need to be produced, and then subclasses are responsible for producing the corresponding components. A Windows factory will only produce Windows components, and a Linux factory will only produce Linux components, each doing its job.

public interface ComponentFactory {

	// Production button
	Button createButton(a);

	// Produce the textbox
	Text createText(a);

	// Production chart
	Chart createChart(a);
}

// Windows Component factory
public class WindowsComponentFactory implements ComponentFactory{

	@Override
	public Button createButton(a) {
		return new WindowsButton();
	}

	@Override
	public Text createText(a) {
		return new WindowsText();
	}

	@Override
	public Chart createChart(a) {
		return newWindowsChart(); }}// Linux component factory
public class LinuxComponentFactory implements ComponentFactory{

	@Override
	public Button createButton(a) {
		return new LinuxButton();
	}

	@Override
	public Text createText(a) {
		return new LinuxText();
	}

	@Override
	public Chart createChart(a) {
		return newLinuxChart(); }}Copy the code

Application relies on the component factory to produce the component, with the class modified slightly:

public class Application {
	private Button button;
	private Text text;
	private Chart chart;

	public Application(ComponentFactory factory) {
		this.button = factory.createButton();
		this.text = factory.createText();
		this.chart = factory.createChart();
	}

	public void buttonClick(a){
		button.click();
	}

	public void textDisplay(a){
		text.display();
	}

	public void showChart(a){ chart.show(); }}Copy the code

At this point, the entire structure is out, and the final class diagram is as follows:Client call:

public class Client {
	public static void main(String[] args) {
		Application windows = new Application(new WindowsComponentFactory());
		windows.buttonClick();
		windows.textDisplay();
		windows.showChart();

		Application linux = new Application(newLinuxComponentFactory()); linux.buttonClick(); linux.textDisplay(); linux.showChart(); }} The Windows button is clicked on the Windows text box to display the Windows chartCopy the code

This is the abstract factory pattern!

2. Abstract the definition of the factory pattern

Provides an interface for creating a set of related or interdependent objects without specifying their concrete classes.

Abstract factory pattern generic class diagram

  • Factory: A Factory abstraction that defines the functions of the Factory and what products it needs to produce.
  • ConcreteFactory: Factory implementation that produces a family of products.
  • Product: A Product abstraction that defines the features and methods that a Product has.
  • ConcreteProduct: ConcreteProduct implementation.

The abstract factory pattern is an updated version of the factory method pattern. The factory method pattern can only produce a single category of products, while the abstract factory pattern can produce a group of related or interrelated products, also known as a product family. There are N product families, so the abstract factory should have N methods. If there are multiple business varieties, it is good to generate objects by abstracting the factory pattern.

1. Advantages and disadvantages of the factory method pattern

advantages

  1. Good encapsulation, the client does not care about the product implementation class, only care about the factory, and the abstraction of the product, comply with the dependency inversion principle.
  2. You can guarantee that clients only use objects within the same product family.
  3. The constraints within the product family are transparent to the client, such that the abstract factory pattern ensures that N product B is produced for every M product A.

disadvantages

  1. Product families are difficult to expand, and if a product class is added, the abstract factory and all factory implementations need to be modified, which does not comply with the open closed principle.

Abstract factory pattern although the product family is difficult to extend, but the product level is very unified extension, for example, Application for the Mac system also develop a set, only need to implement the Mac system components, and the Mac system ComponentFactory, other areas do not need to be modified.

4. To summarize

The abstract factory pattern is an extension of the factory method pattern, which can only produce a single category of products, whereas the abstract factory pattern can produce a set of related or interdependent product families. The product level of the abstract method pattern is very easy to extend, but the product family is difficult to extend. Therefore, the abstract factory pattern is more suitable for scenarios where the product structure is relatively stable than for structures where product classes may be added or removed frequently.