一、模式说明

  前面学习了工厂方法(Factory Method)模式。在工厂方法模式中,在工厂方法模式中,父类决定如何生成实例,但并不决定所要生成的具体类,具体的处理交由子类来处理。这里学习的抽象工厂方法模式中,抽象工厂使用抽象的零件组装成抽象的产品。即使用包含特定的方法接口零件,将零件组装成抽象产品。

二、模式类图:

  上面的类图中包含两个包:包含抽象工厂,抽象零件,抽象产品的类所在的包以及具体工厂实现类的包。

三、代码示例

1、Item类:

package com.designpattern.cn.abstractfactorypattern.abstractfactory;

//抽象的零件Item
public abstract class Item {
protected String caption;
public Item(String caption){
this.caption = caption;
}
public abstract String makeHtml();
}

Item类是下面两个产品的父类,其中的MakeHtml是抽象方法,需要在子类中实现。

2、Link类:

package com.designpattern.cn.abstractfactorypattern.abstractfactory;

//抽象的零件Link
public abstract class Link extends Item {
protected String url;
public Link(String caption, String url){
super(caption);
this.url = url;
}
}

Link类被定义为抽象类,初看似乎并不包含抽象方法,但是,Link类继承了抽象类Item,且没有实现MakeHtml抽象方法,则Link类还是一个抽象类。

3、Tray类:

package com.designpattern.cn.abstractfactorypattern.abstractfactory;

import java.util.ArrayList;

//抽象的Tray类
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);
}
}

同样的Tray类也是抽象类。

4、抽象的产品Product类:

package com.designpattern.cn.abstractfactorypattern.abstractfactory;

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();
}

5、抽象工厂Factory类:

package com.designpattern.cn.abstractfactorypattern.abstractfactory;

public abstract class Factory {
public static Factory getFactory(String classname){
Factory factory = null;
try {
factory = (Factory)Class.forName(classname).newInstance();
}catch (ClassNotFoundException | InstantiationException | IllegalAccessException 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);
}

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

  需要注意的是,虽然getFactory方法生成的是具体工厂的实例,但由于返回值的类型是抽象工厂类型。createLink、createTray、createPage方法是用于在抽象工厂中生成抽象零件和产品的抽象方法,具体的实现交由子类,不过在这里确定了方法的名字和签名。

  看完了模式的抽象类,接下来看具体的实现类:

1、具体的工厂ListFactory类:

package com.designpattern.cn.abstractfactorypattern.listfactory;

import com.designpattern.cn.abstractfactorypattern.abstractfactory.Factory;
import com.designpattern.cn.abstractfactorypattern.abstractfactory.Link;
import com.designpattern.cn.abstractfactorypattern.abstractfactory.Page;
import com.designpattern.cn.abstractfactorypattern.abstractfactory.Tray; public class ListFactory extends Factory {
public Link createLink(String caption, String url){
return new ListLink(caption, url);
} public Tray createTray(String trayname){
return new ListTray(trayname);
} public Page createPage(String title, String author){
return new ListPage(title, author);
}
}

2、具体的零件ListLink类:

package com.designpattern.cn.abstractfactorypattern.listfactory;

import com.designpattern.cn.abstractfactorypattern.abstractfactory.Link;

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";
}
}

3、具体的零件ListTray类:

package com.designpattern.cn.abstractfactorypattern.listfactory;

import com.designpattern.cn.abstractfactorypattern.abstractfactory.Item;
import com.designpattern.cn.abstractfactorypattern.abstractfactory.Tray; import java.util.Iterator; public class ListTray extends Tray {
public ListTray(String caption) {
super(caption);
} @Override
public String makeHtml() {
StringBuffer buffer = new StringBuffer();
buffer.append("<li>\n");
buffer.append(caption + "\n");
buffer.append("<ul>\n");
Iterator iterator = tray.iterator();
while(iterator.hasNext()){
Item item = (Item) iterator.next();
buffer.append(item.makeHtml());
}
buffer.append("</ul>\n");
buffer.append("</li>\n");
return buffer.toString();
}
}

4、具体的零件LIstPage类:

package com.designpattern.cn.abstractfactorypattern.listfactory;

import com.designpattern.cn.abstractfactorypattern.abstractfactory.Item;
import com.designpattern.cn.abstractfactorypattern.abstractfactory.Page; import java.util.Iterator; 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 iterator = content.iterator();
while(iterator.hasNext()){
Item item = (Item)iterator.next();
buffer.append(item.makeHtml());
}
buffer.append("</ul>\n");
buffer.append("<hr><address>" + author + "</address>");
buffer.append("</body></html>\n");
return buffer.toString();
}
}

5、运行结果:

Main类代码:

package com.designpattern.cn.abstractfactorypattern;

import com.designpattern.cn.abstractfactorypattern.abstractfactory.Factory;
import com.designpattern.cn.abstractfactorypattern.abstractfactory.Link;
import com.designpattern.cn.abstractfactorypattern.abstractfactory.Page;
import com.designpattern.cn.abstractfactorypattern.abstractfactory.Tray;
import com.designpattern.cn.abstractfactorypattern.listfactory.ListFactory; public class Main {
public static void main(String[] args){
System.out.println(ListFactory.class.getName());
if(args.length!= 1){
System.out.println("Usage: java Main class.name.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 people = factory.createLink("People's Daily", "http://www.people.com.cn/");
Link gmw = factory.createLink("gmw", "http://www.gmw.cn/");
Link us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
Link jp_yahoo = factory.createLink("Yahoo!", "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(" Daily ");
traynews.add(people);
traynews.add(gmw); Tray trayyahoo = factory.createTray("Yahoo!");
trayyahoo.add(us_yahoo);
trayyahoo.add(jp_yahoo); Tray traysearch = factory.createTray("Search engeen");
traysearch.add(trayyahoo);
traysearch.add(excite);
traysearch.add(google); Page page = factory.createPage("LinkPage", "Rumble");
page.add(traynews);
page.add(traysearch);
page.output();
}
}

四、模式中的角色

  • AbstractProduct抽象产品角色:AbstractProduct负责定义AbstractFactory抽象工厂角色所生成的零件和产品接口。(程序示例中的LInk、Tray、Page类)
  • AbstractFactory抽象工厂角色:负责定义用于生成抽象产品的接口。
  • Client委托者角色:Client调用AbstractFactory和Abstract Product角色的接口来进行工作。程序中由Main扮演该角色。

五、抽象工厂模式的特点

  • 易于增加具体的工厂:很清楚实现一个具体的工厂应该实现哪些方法,对于示例,当需要增加新的工厂时,需要做的就是编写Factory、Link、Tray、Page这几个类的子类。任何时候都不需要修改抽象类和Main类。
  • 难以增加新零件:如果要在一个抽象工厂中增加零件,这时候除了修改抽象工厂,还要修改所有的实例工厂。

六、相关的设计模式

  • Builder模式:分阶段的制作复杂实例
  • Factory Method模式:在抽象工厂Abstract Factory模式中,生成零件和产品可能会使用到工厂方法模式
  • Composite模式
  • Singleton模式

最后,抽象工厂模式在Spring中也是有用到的,所以需要好好消化一下。

一天一个设计模式——Abstract Factory抽象工厂模式的更多相关文章

  1. 2.设计模式-Abstract Factory 抽象工厂模式

    大神勿喷,不对的地方请指出来,学笔记而已. 解决的问题:应对多系列对象构建的变化或多系列(例如:崎岖的山路和平坦的马路属于一个系列) 不断的变化的创建. 使用场景:对象不变(比如有3个对象 " ...

  2. 设计模式(一): abstract factory抽象工厂模式 -- 创建型模式

    1.定义 为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类. 2.适用场景 1.一个系统要独立于它的产品创建.组合和表示. 2.一个系统要由多个产品系列中的一个来配置. 3.当你要 ...

  3. c++ 设计模式9 (Abstract Factory 抽象工厂模式)

    5.2 抽象工厂模式 动机:在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作:同时,由于需求的变化,往往存在更多系列对象的创建工作. 代码示例: 实现利用数据库的业务逻辑,支持多数据库(Sq ...

  4. Java设计模式:Abstract Factory(抽象工厂)模式

    概念定义 抽象工厂(Abstract Factory)模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂模式中,系统的产品有多于一个的产品族(一个产品族里定义多个产品) ...

  5. 面向对象设计模式纵横谈:Abstract Factory 抽象工厂模式(笔记记录)

         今天是设计模式的第二讲,抽象工厂的设计模式,我们还是延续老办法,一步一步的.演变的来讲,先来看看一个对象创建的问题. 1.如何创建一个对象 常规的对象创建方法: 这样的创建对象没有任何问题, ...

  6. Abstract Factory抽象工厂模式

    抽象工厂模式是是用一个超级工厂去创建其他工厂,简单点说就是工厂的父类,属于创建型模式. 目标:提供一个创建一组对象的方法,而无需指定它们具体的类(同工厂方法). 使用场景:系统的产品有多于一个的产品族 ...

  7. Abstract Factory 抽象工厂模式

    提供一个创建一些列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂顾名思义就是对工厂的抽象,它提供了一组创建抽象产品对象的操作接口,我们实际使用的是抽象工厂的派生类,派生类中提供了操作的具 ...

  8. 设计模式 -- Abstract Factory 抽象工厂

    1.常规的对象创建方法 //创建一个Road对象 Road road=new Road(); new的问题:实现依赖,不能应对“具体实例化类型”额变化. 解决思想: 封装变化点--哪里变化,封装哪里( ...

  9. 设计模式02: Abstract Factory 抽象工厂(创建型模式)

    Abstract Factory 抽象工厂(创建型模式) 常见的对象创建方法:    //创建一个Road对象    Road road=new Road();    new的问题:    -实现依赖 ...

随机推荐

  1. postgres 删除外部表

    drop external table if exists tableName;

  2. zabbix监控memcached服务

    zabbix监控memcached服务 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装并配置memcached服务 1>.使用yum方式安装memcached [ro ...

  3. RIOT笔记

    RIOT笔记 2016-04-25 [资源] 维基 https://github.com/RIOT-OS/RIOT/wiki 代码 https://github.com/RIOT-OS/RIOT 网页 ...

  4. element设置headers添加token

    <template>   <div>     <el-upload       action="http://localhost:3000/picture&qu ...

  5. 把自己的项目发布到maven仓库并在maven和gradle中开始使用

    把自己的项目发布到maven仓库并在maven和gradle中开始使用 上一条博客中提到的日志打印项目总算是维护的差不多了, 不过现在使用它还是打成jar包放到其他项目内, 所以决定把项目传到mave ...

  6. 配置 git公钥报错:unknown key type -rsa

    配置 git公钥的时候出现:ssh-keygen unknown key type -rsa 一个解决办法是去本地寻找.ssh文件,参考路径(C:\Users\Administrator.ssh),把 ...

  7. 025、Java中字符串连接与加法操作一起出现

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  8. ACM-Antiprime数

      问题描述: swust打不开,随便找了个博客.... 对于任何正整数x,起约数的个数记做g(x).例如g(1)=1,g(6)=4. 定义:如果某个正整数x满足:对于任意i(0<i<x) ...

  9. NO5 grep-head-tail命令

    ·*****grep:#过滤需要的内容(linux三剑客).                   -v:排除内容.eg:grep -v oldboy test.txt ·head: #头,头部.读取文 ...

  10. HihoCoder第十二周:刷油漆

    #1055 : 刷油漆 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上回说到,小Ho有着一棵灰常好玩的树玩具!这棵树玩具是由N个小球和N-1根木棍拼凑而成,这N个小球 ...