[JAVA] Abstract Factory pattern

What is the Abstract Factory pattern?

Make an abstract product by combining abstract parts. Instead of focusing on the specific implementation of the component, focus on the interface (API). Then, the parts are assembled and the products are put together using only the interface (API).

The role of Abstract Product

The Abstract Product role defines the interface of abstract parts and products created by the Abstract Factory role.

package factory;

/**
 *A class that abstractly represents HTML hyperlinks
 *
 */
public abstract class Link extends Item{
	//For holding the URL of the link destination
	protected String url;

	 public Link(String caption, String url) {
		 super(caption);
		 this.url = url;
	}
}
package factory;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;

/**
 *A class that abstractly represents the entire HTML page
 *
 */
public abstract class Page {
	protected String title;
	protected String author;
	protected ArrayList<Item> content = new ArrayList<>();

	public Page(String title, String author) {
		this.title = title;
		this.author = author;
	}

	public void add(Item item) {
		content.add(item);
	}

	public void output() {
		try {
			String fileName = title + ".html";
			Writer writer = new FileWriter(fileName);
			writer.write(this.makeHtml());
			writer.close();
			System.out.println(fileName + "is created.");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public abstract String makeHtml();
}
package factory;

import java.util.ArrayList;
/**
 *A class that represents a collection of multiple Links and Tray
 *
 */
public abstract class Tray extends Item{
	protected ArrayList<Item> tray = new ArrayList<>();

	 public Tray(String caption) {
		 super(caption);
	}

	 public void add(Item item) {
		 tray.add(item);
	 }
}

The role of Abstract Factory

The AbstractFactory role defines the interface for creating an instance of the AbstractProduct role.

package factory;

/**
 *A class that creates a specific factory instant by specifying a class name
 *
 */
public abstract class Factory {
	public static Factory getFactory(String className) {
		Factory factory = null;
		try {
			factory = (Factory)Class.forName(className).newInstance();
		} catch (ClassCastException e) {
			System.out.println("class" + className + "Cannot be found.");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return factory;
	}

	public abstract Link createLink(String caption, String url);
	public abstract Tray createTray(String caption);
	public abstract Page createPage(String title, String author);

}

The role of Client

The Client role is a role that works using only the interface between the Abstract Factory role and the Abstract Product role. The client role does not know about specific parts, products or factories.

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class Main {

	public static void main(String[] args) {

		if (args.length != 1) {
			System.out.println("Usage: java Main class.mame.of.ConcreateFactory");
			System.out.println("Example 1: java Main listfactory,ListFactory");
			System.out.println("Example 2: java Main tablefactory,TableFactory");
			System.exit(0);
		}

		Factory factory = Factory.getFactory(args[0]);

		Link asahi = factory.createLink("Asahi Shimbun", "http://www.asahi.com/");
		Link yomiuri = factory.createLink("Yomiuri Shimbun", "http://www.yomiuri.co.jp/");

		Link usYahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
		Link jpYahoo = factory.createLink("Yahoo!Japan", "http://www.yahoo.co.jp");
		Link excite = factory.createLink("Excite", "http://www.excite.com/");
		Link google = factory.createLink("Google", "http://www.google.com/");

		Tray trayNews = factory.createTray("newspaper");
		trayNews.add(asahi);
		trayNews.add(yomiuri);

		Tray trayYahoo = factory.createTray("Yahoo!");
		trayYahoo.add(usYahoo);
		trayYahoo.add(jpYahoo);

		Tray traySearch = factory.createTray("Search engine");
		traySearch.add(trayYahoo);
		traySearch.add(excite);
		traySearch.add(google);

		Page page = factory.createPage("LinkPage", "Taro Tanaka");
		page.add(trayNews);
		page.add(traySearch);
		page.output();
	}

}

The role of Concrete Product

In the role of Conctete Product, the interface (API) of the role of Abstract is implemented.

package listFactory;

import factory.Link;

public class ListLink extends Link{

	public ListLink(String caption, String url) {
		super(caption, url);
	}

	public String makeHtml() {
		return " <li><a href=\"" + url + "\">" + caption + "</a></li>\n";
	}

}
package listFactory;

import java.util.Iterator;

import factory.Item;
import factory.Page;

public class ListPage extends Page{

	public ListPage(String title, String author) {
		super(title, author);
	}

	@Override
	public String makeHtml() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("<html><head><title>" + title + "</title></head>\n");
		buffer.append("<body>\n");
		buffer.append("<h1>" + title + "</h1>\n");
		buffer.append("<ul>\n");
		Iterator<Item> it = content.iterator();
		while (it.hasNext()) {
			Item item = it.next();
			buffer.append(item.makeHtml());
		}
		buffer.append("</ul>\n");
		buffer.append("<hr><address>" + author + "</address>");
		buffer.append("</body></html>\n");
		return buffer.toString();
	}
}
package listFactory;

import java.util.Iterator;

import factory.Item;
import factory.Tray;

public class ListTray extends Tray {

	public ListTray(String caption) {
		super(caption);
	}

	public String makeHtml() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("<li>\n");
		buffer.append(caption + "\n");
		buffer.append("<ul>\n");
		Iterator<Item> it = tray.iterator();
		while (it.hasNext()) {
			Item item = it.next();
			buffer.append(item.makeHtml());
		}
		buffer.append("</ul>\n");
		buffer.append("</li>\n");
		return buffer.toString();
	}
}

The role of Concrete Factory

In the Concrete Factory role, the interface (API) of the Abstract Factory role is defined.

package listFactory;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class ListFactory extends Factory {

	@Override
	public Link createLink(String caption, String url) {
		return new ListLink(caption, url);
	}

	@Override
	public Tray createTray(String caption) {
		return new ListTray(caption);
	}

	@Override
	public Page createPage(String title, String author) {
		return new ListPage(title, author);
	}
}

An html file created by passing tableFactory.TableFactory as an argument and executing it

スクリーンショット 2020-09-04 15.50.31.png

Add another concrete factory

It was easy to add a factory. Because it is clear what kind of class should be created and what kind of method should be implemented.

package tableFactory;

import factory.Link;

public class TableLink extends Link {

	public TableLink(String caption, String url) {
		super(caption, url);
	}

	@Override
	public String makeHtml() {
		return "<td><a href=\"" + url + "\">" + caption + "</a></td>\n";
	}
}
package tableFactory;

import java.util.Iterator;

import factory.Item;
import factory.Page;

public class TablePage extends Page {

	public TablePage(String title, String author) {
		super(title, author);
	}

	@Override
	public String makeHtml() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("<html><head><title>" + title + "</title></head>\n");
		buffer.append("<body>\n");
		buffer.append("<h1>" + title + "</h1>\n");
		buffer.append("<table width=\"80%\" border=\"3\">\n");
		Iterator<Item> it = content.iterator();
		while (it.hasNext()) {
			Item item = it.next();
			buffer.append("<tr>" + item.makeHtml() + "</tr>");
		}
		buffer.append("</table>\n");
		buffer.append("<hr><address>" + author + "</address>");
		buffer.append("</body></html>\n");
		return buffer.toString();
	}
}
package tableFactory;

import java.util.Iterator;

import factory.Item;
import factory.Tray;

public class TableTray extends Tray {

	public TableTray(String caption) {
		super(caption);
	}

	@Override
	public String makeHtml() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("<td>");
		buffer.append("<table width=\"100%\" border=\"1\"><tr>");
		buffer.append("<td bgcolor=\"#cccccc\" align=\"center\" colspan=\"" + tray.size() + "\"><b>" + caption + "</b></td>");
		buffer.append("</tr>\n");
		buffer.append("<tr>\n");
		Iterator<Item> it = tray.iterator();
		while (it.hasNext()) {
			Item item = it.next();
			buffer.append(item.makeHtml());
		}
		buffer.append("</tr></table>");
		buffer.append("</td>");
		return buffer.toString();
	}
}
package tableFactory;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class TableFactory extends Factory {

	@Override
	public Link createLink(String caption, String url) {
		return new TableLink(caption, url);
	}

	@Override
	public Tray createTray(String caption) {
		return new TableTray(caption);
	}

	@Override
	public Page createPage(String title, String author) {
		return new TablePage(title, author);
	}
}

Main which is the client role is not changed at all, and the html file created by executing with the argument at runtime set to tableFactory.TableFactory

スクリーンショット 2020-09-04 15.57.57.png

https://github.com/aki0207/abstractFactory

I used this as a reference. Augmented and Revised Introduction to Design Patterns Learned in Java Language

Recommended Posts

abstract Factory Pattern
Abstract Factory pattern
Design pattern ~ Abstract Factory ~
Factory Method Pattern
Factory Method pattern
Design pattern ~ Factory Method ~
Advantages of generating an Abstract Factory pattern with an enum
Introduction to Design Patterns (Abstract Factory)
Java beginner design pattern (Factory Method pattern)
Prototype pattern
Memento Pattern
What a Strategy pattern Factory, not a State
Mediator pattern
Iterator pattern
Composite pattern
Observer Pattern
Builder pattern
Bridge Pattern
Command Pattern
Builder Pattern
Strategy pattern
Iterator Pattern
Visitor pattern
Adapter Pattern
Proxy Pattern
Strategy Pattern
Composite Pattern
Singleton Pattern
Singleton pattern
Prototype Pattern
Facade Pattern
Decorator pattern
Flyweight Pattern
Decorator Pattern
Mediator Pattern
Facade pattern
Visitor Pattern
Bridge pattern