该文章是阅读《图解设计模式》的学习笔记。书本链接https://www.ituring.com.cn/book/1811
在前面已经学习过了Factory Method以及Builder模式,之前的Factory Method(工厂方法)模式是使用单个零件组装成产品。而Builder模式是用于组装具有复杂结构的实例。本次学习的抽象工厂模式结合了工厂方法和建设者模式的特点。抽象工厂类通过抽象零件组装成抽象产品。下面以使用列表和表格两种形式组装网页页面为例展现抽象工厂模式。 factory包里面的代码:
Factory抽象类代码:
package com.wen.AbstractFactory.factory;
public abstract class Factory {
public static Factory getFactory(String classname) {
Factory factory = null;
try {
factory = (Factory)Class.forName(classname).newInstance();
} catch (ClassNotFoundException e) {
System.err.println("没有找到 " + classname + "类。");
} 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);
}
Item抽象类代码:
package com.wen.AbstractFactory.factory;
public abstract class Item {
protected String caption;
public Item(String caption) {
this.caption = caption;
}
public abstract String makeHTML();
}
Link抽象类代码:
package com.wen.AbstractFactory.factory;
public abstract class Link extends Item {
protected String url;
public Link(String caption, String url) {
super(caption);
this.url = url;
}
}
Page抽象类代码:
package com.wen.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 String author;
protected ArrayList 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 + " 编写完成。");
} catch (IOException e) {
e.printStackTrace();
}
}
public abstract String makeHTML();
}
Tray抽象类代码:
package com.wen.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);
}
}
ListFactory包里的代码:
ListFactory类代码:
package com.wen.AbstractFactory.ListFactory;
import com.wen.AbstractFactory.factory.Factory;
import com.wen.AbstractFactory.factory.Link;
import com.wen.AbstractFactory.factory.Page;
import com.wen.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, String author) {
return new ListPage(title, author);
}
}
ListLink类代码:
package com.wen.AbstractFactory.ListFactory;
import com.wen.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";
}
}
ListPage类代码:
package com.wen.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 String author;
protected ArrayList 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 + " 编写完成。");
} catch (IOException e) {
e.printStackTrace();
}
}
public abstract String makeHTML();
}
ListTray类代码:
package com.wen.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 String author;
protected ArrayList 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 + " 编写完成。");
} catch (IOException e) {
e.printStackTrace();
}
}
public abstract String makeHTML();
}
TableFactory包里的代码:
TableFactory类代码:
package com.wen.AbstractFactory.TableFactory;
import com.wen.AbstractFactory.factory.Factory;
import com.wen.AbstractFactory.factory.Link;
import com.wen.AbstractFactory.factory.Page;
import com.wen.AbstractFactory.factory.Tray;
public class TableFactory extends Factory {
public Link createLink(String caption, String url) {
return new TableLink(caption, url);
}
public Tray createTray(String caption) {
return new TableTray(caption);
}
public Page createPage(String title, String author) {
return new TablePage(title, author);
}
}
TableLink类代码:
package com.wen.AbstractFactory.TableFactory;
import com.wen.AbstractFactory.factory.Link;
public class TableLink extends Link {
public TableLink(String caption, String url) {
super(caption, url);
}
public String makeHTML() {
return "<td><a href=\"" + url + "\">" + caption + "</a></td>\n";
}
}
TablePage类代码:
package com.wen.AbstractFactory.TableFactory;
import com.wen.AbstractFactory.factory.Item;
import com.wen.AbstractFactory.factory.Page;
import java.util.Iterator;
public class TablePage extends Page {
public TablePage(String title, String author) {
super(title, author);
}
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 it = content.iterator();
while (it.hasNext()) {
Item 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();
}
}
TableTray类代码:
package com.wen.AbstractFactory.TableFactory;
import com.wen.AbstractFactory.factory.Item;
import com.wen.AbstractFactory.factory.Tray;
import java.util.Iterator;
public class TableTray extends Tray {
public TableTray(String caption) {
super(caption); // 使用super(...)表达式
}
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 it = tray.iterator();
while (it.hasNext()) {
Item item = (Item)it.next();
buffer.append(item.makeHTML());
}
buffer.append("</tr></table>");
buffer.append("</td>");
return buffer.toString();
}
}
Main入口类代码:
package com.wen.AbstractFactory;
import com.wen.AbstractFactory.factory.Factory;
import com.wen.AbstractFactory.factory.Link;
import com.wen.AbstractFactory.factory.Page;
import com.wen.AbstractFactory.factory.Tray;
public class Main {
public static void main(String[] args) {
if(args.length != 1){
System.out.println("使用:java Main + 具体工厂类包的名字");
System.out.println("例1:java Main listfactor.ListFactory");
System.out.println("例2:java Main listfactor.TableFactory");
}
Factory factory = Factory.getFactory("com.wen.AbstractFactory.ListFactory.ListFactory");
// Factory factory = Factory.getFactory("com.wen.AbstractFactory.TableFactory.TableFactory");
Link foodie = factory.createLink("吃货谷","https://www.chihuogu.com/");
Link foodie2 = factory.createLink("吃货网","https://www.ytn808.com/");
Link foodie3 = factory.createLink("中国吃货谷","http://www.clhoo.com/");
Link foodie4 = factory.createLink("吃货俱乐部","http://www.chihuoclub.com/index");
Link foodie5 = factory.createLink("吃货值得买","http://www.chzdm.com/");
Link foodie6 = factory.createLink("美食杰","https://www.meishij.net/china-food/");
Tray trayfoodie1 = factory.createTray("吃货链接");
trayfoodie1.add(foodie);
trayfoodie1.add(foodie2);
Tray trayfoodie2 = factory.createTray("嵌套吃货链接");
trayfoodie2.add(foodie3);
trayfoodie2.add(foodie4);
Tray trayfoodie3 = factory.createTray("再次嵌套吃货链接");
trayfoodie3.add(trayfoodie2);
trayfoodie3.add(foodie5);
trayfoodie3.add(foodie6);
Page page = factory.createPage("ListFactory","一个不愿意透漏姓名的吃货");
// Page page = factory.createPage("TableFactory","一个不愿意透漏姓名的吃货");
//去掉对应注释即可运行生成TableFactory文件
page.add(trayfoodie1);
page.add(trayfoodie3);
page.output();
}
}
通过ListFactory生成的文件内容:
通过TableFactory生成的文件内容:
分析该模式中的角色:
AbstractFactory(抽象产品):负责定义抽象零件的接口。
AbstractFactory(抽象工厂):负责定义生成抽象产品的接口。
ConcreteProduct(具体产品) :负责实现抽象产品的接口
ConcreteFactory(具体工厂):负责实现抽象工厂的接口
Client(请求者):调用抽象产品和抽象工厂的方法,对具体的工厂和产品一无所知,通过指定类名调用对应的具体类实现对应功能。