抽象工厂的工作是将“抽象零件”组装为“抽象产品”。在抽象工厂模式中将会出现抽象工厂,它会将抽象零件组装为抽象产品。也就是说,我们并不关心零件的具体实现,而是只关心接口。我们仅适用该接口将零件组装起来成为产品。

  

  示例程序的功能是将带有层次关系的链接的集合制作成HTML文件。

 1 package bigjunoba.bjtu.factory;
 2
 3 public abstract class Item {
 4     protected String caption;
 5
 6     public Item(String caption) {
 7         this.caption = caption;
 8     }
 9
10     public abstract String makeHTML();
11 }

  Item类是Link类和Tray类的父类。这样,Link类和Tray类就具有可替换性了。caption字段表示项目的“标题”。

 1 package bigjunoba.bjtu.factory;
 2
 3 public abstract class Link extends Item {
 4     protected String url;
 5
 6     public Link(String caption, String url) {
 7         super(caption);
 8         this.url = url;
 9     }
10 }

  Link类是抽象地表示HTML的超链接的类。url字段中保存的是超链接所指向的地址。由于Link类中没有实现父类的抽象方法makeHTML,因此它也是抽象类。

 1 package bigjunoba.bjtu.factory;
 2 import java.util.ArrayList;
 3
 4 public abstract class Tray extends Item {
 5     protected ArrayList<Item> tray = new ArrayList<Item>();
 6     public Tray(String caption) {
 7         super(caption);
 8     }
 9     public void add(Item item) {
10         tray.add(item);
11     }
12 }

  Tray类表示的是一个含有多个Link类和Tray类的容器。add方法将Link类和Tray类集合在一起。同理,也没有实现父类的抽象方法makeHTML,因此它也是抽象类。

 1 package bigjunoba.bjtu.factory;
 2
 3 import java.io.*;
 4 import java.util.ArrayList;
 5
 6 public abstract class Page {
 7     protected String title;
 8     protected String author;
 9     protected ArrayList<Item> content = new ArrayList<Item>();
10
11     public Page(String title, String author) {
12         this.title = title;
13         this.author = author;
14     }
15
16     public void add(Item item) {
17         content.add(item);
18     }
19
20     public void output() {
21         try {
22             String filename = title + ".html";
23             Writer writer = new FileWriter(filename);
24             writer.write(this.makeHTML());
25             writer.close();
26             System.out.println(filename + " 编写完成。");
27         } catch (IOException e) {
28             e.printStackTrace();
29         }
30     }
31
32     public abstract String makeHTML();
33 }

  Page是抽象地表示HTML页面的类。如果将Link和Tray比喻成抽象的“零件”,那么Page类就是抽象的“产品”。使用add方法向页面中增加Item,output方法首选根据页面标题确定文件名,接着调用makeHTML方法(为了强调调用的是自己的makeHTML方法,直接显式地加上了this)将自身保存的HTML内容写入到文件中。

 1 package bigjunoba.bjtu.factory;
 2
 3 public abstract class Factory {
 4     public static Factory getFactory(String classname) {
 5         Factory factory = null;
 6         try {
 7             factory = (Factory)Class.forName(classname).newInstance();
 8         } catch (ClassNotFoundException e) {
 9             System.err.println("没有找到 " + classname + "类。");
10         } catch (Exception e) {
11             e.printStackTrace();
12         }
13         return factory;
14     }
15     public abstract Link createLink(String caption, String url);
16     public abstract Tray createTray(String caption);
17     public abstract Page createPage(String title, String author);
18  }

  Factory类中的getFactory方法,可以根据指定的类名生成具体工厂的实例。getFactory方法通过调用Class类的forName方法来动态地读取类信息,接着使用newInstance方法生成该类的实例,并将其作为返回值返回给调用者。

 1 package bigjunoba.bjtu.test;
 2
 3 import bigjunoba.bjtu.factory.*;
 4
 5 public class Main {
 6     public static void main(String[] args) {
 7         if (args.length != 1) {
 8             System.out.println("Usage: java Main class.name.of.ConcreteFactory");
 9             System.out.println("Example 1: java Main bigjunoba.bjtu.listfactory.ListFactory");
10             System.out.println("Example 2: java Main bigjunoba.bjtu.tablefactory.TableFactory");
11             System.exit(0);
12         }
13         Factory factory = Factory.getFactory(args[0]);
14
15         Link people = factory.createLink("人民日报", "http://www.people.com.cn/");
16         Link gmw = factory.createLink("光明日报", "http://www.gmw.cn/");
17
18         Link us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
19         Link jp_yahoo = factory.createLink("Yahoo!Japan", "http://www.yahoo.co.jp/");
20         Link excite = factory.createLink("Excite", "http://www.excite.com/");
21         Link google = factory.createLink("Google", "http://www.google.com/");
22
23         Tray traynews = factory.createTray("日报");
24         traynews.add(people);
25         traynews.add(gmw);
26
27         Tray trayyahoo = factory.createTray("Yahoo!");
28         trayyahoo.add(us_yahoo);
29         trayyahoo.add(jp_yahoo);
30
31         Tray traysearch = factory.createTray("检索引擎");
32         traysearch.add(trayyahoo);
33         traysearch.add(excite);
34         traysearch.add(google);
35
36         Page page = factory.createPage("LinkPage", "杨文轩");
37         page.add(traynews);
38         page.add(traysearch);
39         page.output();
40     }
41 }

  Main类使用抽象工厂生产零件并将零件组装成产品。由于Main类只引入了一个包,所以可以看出,该类并没有使用任何具体零件、产品和工厂。

 1 package bigjunoba.bjtu.listfactory;
 2
 3 import bigjunoba.bjtu.factory.*;
 4
 5 public class ListFactory extends Factory {
 6     public Link createLink(String caption, String url) {
 7         return new ListLink(caption, url);
 8     }
 9
10     public Tray createTray(String caption) {
11         return new ListTray(caption);
12     }
13
14     public Page createPage(String title, String author) {
15         return new ListPage(title, author);
16     }
17 }

  ListFactory类只是简单地new出了ListLink、ListTray和ListPage的实例。

 1 package bigjunoba.bjtu.listfactory;
 2
 3 import bigjunoba.bjtu.factory.*;;
 4
 5 public class ListLink extends Link {
 6     public ListLink(String caption, String url) {
 7         super(caption, url);
 8     }
 9
10     public String makeHTML() {
11         return "  <li><a href=\"" + url + "\">" + caption + "</a></li>\n";
12     }
13 }

  ListLink类使用<li>和<a>标签来制作HTML片段。

 1 package bigjunoba.bjtu.listfactory;
 2
 3 import bigjunoba.bjtu.factory.*;
 4 import java.util.Iterator;
 5
 6 public class ListTray extends Tray {
 7     public ListTray(String caption) {
 8         super(caption);
 9     }
10
11     public String makeHTML() {
12         StringBuffer buffer = new StringBuffer();
13         buffer.append("<li>\n");
14         buffer.append(caption + "\n");
15         buffer.append("<ul>\n");
16         Iterator<Item> it = tray.iterator();
17         while (it.hasNext()) {
18             Item item = (Item) it.next();
19             buffer.append(item.makeHTML());
20         }
21         buffer.append("</ul>\n");
22         buffer.append("</li>\n");
23         return buffer.toString();
24     }
25 }

  ListTray类中tray字段保存了所有需要以HTML格式输出的Item,而负责将它们以HTML格式输出的就是makeHTML方法。makeHTML方法首先使用<li>标签输出标题,接着使用</ul>和</li>标签输出每个Item。

  每个Item输出为HTML格式的方法就是调用每个Item的makeHTML方法了。这里并不关心变量item中保存的实例的类型究竟是ListLink还是ListTray,只是简单地调用了item.makeHTML()而已。变量item是Item类型的,而Item类又声明了makeHTML方法,而且ListLink类和ListTray类都是Item类的子类,因此可以放心调用。这就是面向对象的优点。

 1 package bigjunoba.bjtu.listfactory;
 2
 3 import bigjunoba.bjtu.factory.*;
 4 import java.util.Iterator;
 5
 6 public class ListPage extends Page {
 7     public ListPage(String title, String author) {
 8         super(title, author);
 9     }
10
11     public String makeHTML() {
12         StringBuffer buffer = new StringBuffer();
13         buffer.append("<html><head><title>" + title + "</title></head>\n");
14         buffer.append("<body>\n");
15         buffer.append("<h1>" + title + "</h1>\n");
16         buffer.append("<ul>\n");
17         Iterator<Item> it = content.iterator();
18         while (it.hasNext()) {
19             Item item = (Item) it.next();
20             buffer.append(item.makeHTML());
21         }
22         buffer.append("</ul>\n");
23         buffer.append("<hr><address>" + author + "</address>");
24         buffer.append("</body></html>\n");
25         return buffer.toString();
26     }
27 }

  ListPage类和ListTray类差不多。

  当只有一个具体工厂的时候,是完全没有必要划分“抽象类”与“具体类”的。还要增加一个tablefactoty将链接以表格形式展示出来。

  代码结构如上图,这里就不写tablefactory部分的代码了。

<html><head><title>LinkPage</title></head>
<body>
<h1>LinkPage</h1>
<ul>
<li>
日报
<ul><li><a href="http://www.people.com.cn/">人民日报</a></li><li><a href="http://www.gmw.cn/">光明日报</a></li>
</ul>
</li>
<li>
检索引擎
<ul>
<li>
Yahoo!
<ul><li><a href="http://www.yahoo.com/">Yahoo!</a></li><li><a href="http://www.yahoo.co.jp/">Yahoo!Japan</a></li>
</ul>
</li><li><a href="http://www.excite.com/">Excite</a></li><li><a href="http://www.google.com/">Google</a></li>
</ul>
</li>
</ul>
<hr><address>杨文轩</address></body></html>

  执行javac Main.java bigjunoba.bjtu.listfactory/ListFactory.java后的结果如上。

<html><head><title>LinkPage</title></head>
<body>
<h1>LinkPage</h1>
<table width="80%" border="3">
<tr><td><table width="100%" border="1"><tr><td bgcolor="#cccccc" align="center" colspan="2"><b>日报</b></td></tr>
<tr>
<td><a href="http://www.people.com.cn/">人民日报</a></td>
<td><a href="http://www.gmw.cn/">光明日报</a></td>
</tr></

  执行javac Main.java bigjunoba.bjtu.tablefactory/TableFactory.java后的结果如上。

  抽象工厂模式的类图。

  抽象工厂的特点:

  1.易于增加具体的工厂。假如要增加新的具体工厂,那么需要做的就是编写Factory、Link、Tray和Page这4个类的子类,并实现它们定义的抽象方法。这样,无论增加多少个具体工厂,都无需修改抽象工厂和Main部分。

  2.难以增加新的零件。假如要在factory包中增加一个表示图像的Picture零件,那就必须要对所有的具体工厂进行相应的修改才行。例如,需要在listfactory包中就必须做到假如createPicture方法和新增ListPictrue类,这样编写完成的具体工厂越多,修改的工作量就会越大。

转载于:https://www.cnblogs.com/BigJunOba/p/8685971.html

设计模式(八)Abstract Factory模式相关推荐

  1. 设计模式学习笔记——抽象工厂(Abstract Factory)模式

    设计模式学习笔记--抽象工厂(Abstract Factory)模式 @(设计模式)[设计模式, 设计模式中文名, 设计模式英文名] 设计模式学习笔记抽象工厂Abstract Factory模式 基本 ...

  2. 设计模式学习笔记三——Abstract Factory模式

    动机:实现一系列相互依赖对象的创建,通过封装系列对象创建来隔离对象创建和客户程序,从而能够灵活提供更多系列对象创建和系列对象间的切换,而不需要改变客户程序. 应用:多种风格软件界面控件的创建.对应多种 ...

  3. 设计模式--抽象工厂(Abstract Factory)模式

    模式定义 提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类 类图 应用场景 程序需要处理不同系列的相关产品,但是你不希望它依赖于这些产品的具体类时可以使用抽象工厂模式 优点 1.可以 ...

  4. 【白话设计模式八】命令模式(Command)

    为什么80%的码农都做不了架构师?>>>    #0 系列目录# 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factory) [白话设计模式二] ...

  5. Abstract Factory模式(抽象工厂模式)

    Abstract Factory模式:将关联零件组装成产品. AbstractProduct(抽象产品) 负责定义AbstractFactory角色所生成的抽象零件和产品的接口(API) Abstac ...

  6. php工程模式,PHP设计模式(八):工厂模式

    Introduction 在PHP设计模式(七):设计模式分类中我们提到过创建设计模式(Creation patterns),创建设计模式专注于设计对象(Object)和实例(Instance)的创建 ...

  7. php设计模式八-----装饰器模式

    1.介绍: 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...

  8. 设计模式-Builder和Factory模式区别

    Builder和Factory模式区别 Builder模式结构: Factory模式一进一出,Builder模式是分步流水线作业. 当你需要做一系列有序的工作或者按照一定的逻辑来完成创建一个对象时 B ...

  9. 设计模式:Abstract Factory和Builder(比较区别,个人认为讲得很明白)

    如果说 Factory和Prototype是同一个层次的话,那么Abstract Factory和Builder就是更高一级的层次. 1 Abstact Factory 在上面的Factory类型中, ...

最新文章

  1. mysql的安装和启动_mysql安装和启动
  2. 创建vue项目(二)引入elementUi、axios、准备静态资源、封装组件(.vue,js代码等)
  3. php实现数字滚动效果,vue如何实现数字滚动增加效果?代码示例
  4. 助力全站WebP ,阿里云云上FPGA 团队发布 WebP图片解决方案
  5. lambda理解与应用
  6. jmu-Java-07多线程-同步访问 (10分)
  7. 从零开始学 Kotlin 之「2」数据类型
  8. 机器学习笔记(一)----基本概念
  9. BIO、NIO、AIO入门认识
  10. 【干货】关于机器学习的知识点,全在这篇文章里了
  11. 今天就来分享一招坐着减肥法~ 办公室“久坐族”也同样适用
  12. 关于引力波的一些疑问
  13. 网络协议篇之CWMP协议(一)—— CWMP(TR-069)基础
  14. 优动漫PAINT画面上色技巧——渐变映射
  15. 2021西湖论剑misc——Yusa的小秘密
  16. Prettier your project
  17. macOS的计时器:Clocker for Mac
  18. <a>链接下载视频 而不是打开新页面播放
  19. PyCharm连接MySQL数据库的时候,驱动下载失败
  20. recovery/removal time

热门文章

  1. 啊哈添柴挑战Java1331. 末位为0?
  2. php 如何实现关键字查找,javascript、php关键字搜索函数的使用方法
  3. 光学设计手册学习(二)——像差
  4. Word框选一整段文字如何防止框到换行符?word怎么在选择的时候不选择上换行符,word选中段尾不选回车符
  5. 常见 TCP 拥塞避免算法浏览(下)
  6. 老家路边的这些野菜你还认识吗?附采摘路线图,收藏!
  7. 项目组织的类型及特点
  8. calibre中的hcell_[ Calibre ] LVS BOX 详细用法
  9. Janus init
  10. 70个Python练手项目列表(都有完整教程)(需要注册实验楼账号)