背景
抽象工厂(Abstract Factory) 的工作是将抽象零件组装成抽象产品
“抽象”是指不考虑具体怎样实现,而是仅关注接口的状态,在abstract factory 模式中将会出现抽象工厂,它会将抽象零件组成为抽象产品。也就是说,我们并不关心零件的具体实现,而是只关心接口(API),我们仅用接口将零件组装成为产品。 体现了依赖倒置原则。
登场角色
AbstractProduct 抽象产品
负责定义AbstractFactory 所需要的零件和产品的 API,如示例代码中的Page,Link,Tray;
AbstractFactory 抽象工厂
负责定义生成零件和产品的API;
Client 委托者
调用 AbstractFactory和 AbstractProduct的方法来工作,对于具体的零件,产品和工厂一无所知,如示例代码中的 Main类;
ConcreteProduct 具体产品
负责实现AbstractProduct角色中的接口,如示例代码中的ListLink类,ListTray类,ListPage类;
ConcreteFactory 具体工厂
负责实现AbstractFactory角色中的接口,如示例代码中的ListFactory类;
类图
代码示例
实现将带有层次关系的链接集合制作成HTML文件
抽象类
Factory类
public abstract class Factory {
public static Factory getFactory(String className) {
Factory factory = null;
try {
factory = (Factory) Class.forName(className).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException 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);
}
Item类,是Link和Tray的父类
public abstract class Item {
// 标题
protected String caption;
public Item(String caption) {
this.caption = caption;
}
public abstract String makeHTML();
}
Page类,表示一个页面
/**
* Page类抽象表示HTML页面的类
* 如果将Link Tray 看作抽象零件,hbn 则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 addItem(Item item) {
content.add(item);
}
/**
* 输出内容到页面
*/
public void output() {
try {
String fileName = title + ".html";
Writer writer = new FileWriter(fileName);
writer.write(this.makeHTML());
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 构造页面的内容
public abstract String makeHTML();
}
Link类,表示链接
/**
* 抽象表示HTML链接的类
*/
public abstract class Link extends Item {
protected String url;
public Link(String caption, String url) {
super(caption);
this.url = url;
}
}
Tray类,表示一个列表,列表中的每一个元素都会含有一个列表
/**
* 表示一个含有多个 link和 tray的容器
*/
public abstract class Tray extends Item {
protected ArrayList<Item> arrayList = new ArrayList<>();
public Tray(String caption) {
super(caption);
}
public void addItem(Item item) {
arrayList.add(item);
}
}
具体实现类
ListFactory类
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);
}
}
ListPage类
public class ListPage extends Page {
public ListPage(String title, String author) {
super(title, author);
}
@Override
public String makeHTML() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("<html><head><title>" + title + "</title></head>\n");
stringBuffer.append("<body>\n");
stringBuffer.append("<h1>" + title +"</h1>\n");
stringBuffer.append("<ul>\n");
Iterator<Item> it = content.iterator();
while (it.hasNext()) {
Item next = it.next();
stringBuffer.append(next.makeHTML());
}
stringBuffer.append("</ul>\n");
stringBuffer.append("<hr><address>" + author + "</address>");
stringBuffer.append("</body></html>\n");
return stringBuffer.toString();
}
}
ListLink类
public class ListLink extends Link {
public ListLink(String caption, String url) {
super(caption, url);
}
@Override
public String makeHTML() {
return "<li><a href="" + url + "">" + caption + "</a></li>\n";
}
}
ListTray类
public class ListTray extends Tray {
public ListTray(String caption) {
super(caption);
}
@Override
public String makeHTML() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("<li>\n");
stringBuffer.append(caption + "\n");
stringBuffer.append("<ul>\n");
Iterator<Item> it = arrayList.iterator();
while (it.hasNext()) {
Item next = it.next();
stringBuffer.append(next.makeHTML());
}
stringBuffer.append("</ul>\n");
stringBuffer.append("</li>\n");
return stringBuffer.toString();
}
}
启动类
public class Main {
public static void main(String[] args) {
Factory factory = Factory.getFactory(args[0]);
Page page = factory.createPage("LinkPage", "杨子轩");
Tray tray1 = factory.createTray("日报");
Tray tray2 = factory.createTray("检索引擎");
Link link1 = factory.createLink("人民日报", "");
Link link2 = factory.createLink("光明日报", "");
tray1.addItem(link1);
tray1.addItem(link2);
Tray yahoo = factory.createTray("Yahoo");
Link yahoo_us = factory.createLink("Yahoo!", "");
Link yahoo_jp = factory.createLink("Yahoo!Japan", "");
yahoo.addItem(yahoo_jp);
yahoo.addItem(yahoo_us);
Link exciteLink = factory.createLink("Excite", "");
Link google = factory.createLink("Google", "");
tray2.addItem(yahoo);
tray2.addItem(exciteLink);
tray2.addItem(google);
page.addItem(tray1);
page.addItem(tray2);
page.output();
}
}
功能分析
- 容易添加新的工厂,只要重写抽象的零件和工厂即可
- 难以添加新的零件,一旦要添加新的零件,就要将其他的具体的工厂进行修改,已经编写完成的具体工厂越多,修改的工作量就会越大