Design Pattern | Abstract Factory Methods
What Is the Abstract Factory Pattern?
- Abstract Factory means an abstract factory.
- Being abstract means focusing only on the interface without considering how it is concretely implemented.
- The Abstract Factory pattern focuses on interfaces rather than the concrete implementation of parts. It assembles parts using only those interfaces and organizes them into products.
- It creates products by combining related parts.
- In GoF design patterns, it is classified as a creational design pattern.
Abstract Factory Pattern Example Program
This example program outputs a favorites list in HTML format.
Class Diagram

1. Factory Class
This class represents an abstract factory. It creates Link, Tray, and Page.
Factory.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
public abstract class Factory {
public abstract Link createLink(String caption, String url);
public abstract Tray createTray(String caption);
public abstract Page createPage(String title);
public static Factory getFactory(String classname) {
Factory factory = null;
try {
factory = (Factory) Class.forName(classname).getDeclaredConstructor().newInstance();
} catch (ClassNotFoundException e) {
System.err.println("클래스 " + classname + "를 찾을 수 없습니다.");
} catch (Exception e) {
e.printStackTrace();
}
return factory;
}
}
2. Item Class
This class treats Link and Tray uniformly.
Item.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
public abstract class Item {
protected String caption;
public Item(String caption) {
this.caption = caption;
}
public abstract String makeHTML();
}
3. Link Class
Abstract part: a class that represents an HTML link.
Link.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
public abstract class Link extends Item {
protected String url;
public Link(String caption, String url) {
super(caption);
this.url = url;
}
}
4. Tray Class
Abstract part: a class that collects Link and Tray.
Tray.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
import java.util.ArrayList;
public abstract class Tray extends Item {
protected ArrayList tray = new ArrayList();
public Tray(String caption) {
super(caption);
}
public void add(Item item) {
tray.add(item);
}
}
5. Page Class
Abstract part: a class that represents an HTML page.
Page.java
package com.devkuma.designpattern.creational.abstractfactory.factory;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
public abstract class Page {
protected String title;
protected ArrayList content = new ArrayList();
public Page(String title) {
this.title = title;
}
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 + "을 생성했습니다.");
} catch (IOException e) {
e.printStackTrace();
}
}
public abstract String makeHTML();
}
6. ListFactory Class
This class represents a concrete factory. It creates ListLink, ListTray, and ListPage.
ListFactory.java
package com.devkuma.designpattern.creational.abstractfactory.listfactory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Factory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Link;
import com.devkuma.designpattern.creational.abstractfactory.factory.Page;
import com.devkuma.designpattern.creational.abstractfactory.factory.Tray;
public class ListFactory extends Factory {
public Link createLink(String caption, String url) {
return new ListLink(caption, url);
}
public Tray createTray(String caption) {
return new ListTray(caption);
}
public Page createPage(String title) {
return new ListPage(title);
}
}
7. ListLink Class
Concrete part: a class that represents an HTML link.
ListLink.java
package com.devkuma.designpattern.creational.abstractfactory.listfactory;
import com.devkuma.designpattern.creational.abstractfactory.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";
}
}
8. ListTray Class
Concrete part: a class that collects Link and Tray.
ListTray.java
package com.devkuma.designpattern.creational.abstractfactory.listfactory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Item;
import com.devkuma.designpattern.creational.abstractfactory.factory.Tray;
import java.util.Iterator;
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 it = tray.iterator();
while (it.hasNext()) {
Item item = (Item) it.next();
buffer.append(item.makeHTML());
}
buffer.append("</ul>\n");
buffer.append("</li>\n");
return buffer.toString();
}
}
9. ListPage Class
Concrete part: a class that represents an HTML page.
ListPage.java
package com.devkuma.designpattern.creational.abstractfactory.listfactory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Item;
import com.devkuma.designpattern.creational.abstractfactory.factory.Page;
import java.util.Iterator;
public class ListPage extends Page {
public ListPage(String title) {
super(title);
}
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 it = content.iterator();
while (it.hasNext()) {
Item item = (Item) it.next();
buffer.append(item.makeHTML());
}
buffer.append("</ul>\n");
buffer.append("</body></html>\n");
return buffer.toString();
}
}
10. Main Class
This is the class that executes the main processing.
Main.java
package com.devkuma.designpattern.creational.abstractfactory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Factory;
import com.devkuma.designpattern.creational.abstractfactory.factory.Link;
import com.devkuma.designpattern.creational.abstractfactory.factory.Page;
import com.devkuma.designpattern.creational.abstractfactory.factory.Tray;
public class Main {
public static void main(String[] args) {
Factory factory = Factory.getFactory("com.devkuma.designpattern.creational.abstractfactory.listfactory.ListFactory");
Link devkuma = factory.createLink("Devkuma", "https://www.devkuma.com//");
Link araikuma = factory.createLink("araikuma", "https://araikuma.tistory.com/");
Link naver = factory.createLink("Naver", "https://www.naver.com/");
Link daum = factory.createLink("Daum", "https://www.daum.com/");
Link google = factory.createLink("Google", "https://www.google.com/");
Tray pgTray = factory.createTray("프로그래밍");
pgTray.add(devkuma);
pgTray.add(araikuma);
Tray searchTray = factory.createTray("검색사이트");
searchTray.add(naver);
searchTray.add(daum);
searchTray.add(google);
Page page = factory.createPage("즐겨찾기");
page.add(pgTray);
page.add(searchTray);
page.output();
}
}
11. Execution Result
The file generated by the program is shown below.
즐겨찾기.html
<html><head><title>즐겨찾기</title></head>
<body>
<h1>즐겨찾기</h1>
<ul>
<li>
프로그래밍
<ul>
<li><a href="https://www.devkuma.com//">Devkuma</a></li>
<li><a href="https://araikuma.tistory.com/">araikuma</a></li>
</ul>
</li>
<li>
검색사이트
<ul>
<li><a href="https://www.naver.com/">Naver</a></li>
<li><a href="https://www.daum.com/">Daum</a></li>
<li><a href="https://www.google.com/">Google</a></li>
</ul>
</li>
</ul>
</body></html>
Advantages of the Abstract Factory Pattern
For example, when adding a new concrete factory to the example program, you create subclasses of Factory, Link, Tray, and Page and implement each abstract method.
In other words, you only concretize the abstract parts held by the classes in the factory package. At this time, no matter how many concrete factories are added, there is no need to modify the abstract factory.