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 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 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 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();
}
}
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();
}
}
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);
}
}
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
https://github.com/aki0207/abstractFactory
I used this as a reference. Augmented and Revised Introduction to Design Patterns Learned in Java Language
Recommended Posts