AbstractFactory抽象工厂设计模式

AbstractFactory模式

Abstract的意思是“抽象的”,Factory的意思是“工厂”。将它们组合起来我们就可以知道AbstractFactory表示“抽象工厂”的意思。

抽象工厂的工作是将“抽象零件”组装为“抽象产品”。

我们并不关心零件的具体实现,而是只关心接口(API)。我们仅使用该接口(API)将零件组装成为产品。


名字说明
factoryFactory表示抽象工厂的类(制作Link,Tray,Page)
factoryItem方便统一处理Link和Tray的类
factoryLink抽象零件:表示HTML的链接的类
factoryTray抽象零件: 表示含有Link和Tray的类
factoryPage抽象零件: 表示HTML页面的类
无名Test测试程序行为的类
listfactoryListFactory表示具体工厂的类(制作ListLink,ListTray等)
listfactoryListLink具体零件:表示HTML的链接的类
listfactoryListTray具体零件:表示含有Link和Tray的类
listfactoryListPage具体零件:表示HTML页面的类

factory包

包含抽象工厂、零件、产品的包。

Item

Item类是Link类和Tray类的父类(Item有“项目”的意思)。这样,Link类和Tray类就具有可替换行了。

caption字段标识项目的“标题”。

makeHTML方法是抽象方法,需要子类来实现这个方法。该方法会返回HTML文件的内容(需要子类去实现)。

package abstractfactory.factory;

/**
 * @author wenei
 * @date 2021-05-23 19:50
 */
public abstract class Item {

    /**
     * 标题
     */
    protected String caption;

    public Item(String caption) {
        this.caption = caption;
    }

    public abstract String makeHTML();
}
Link

Link类是抽象的表示HTML的超链接的类。

url字段中保存的是超链接所指向的地址。

Link类并没有实现父类的makeHTML抽象方法,所以其也是抽象类。

package abstractfactory.factory;

import abstractfactory.factory.Item;

/**
 * @author wenei
 * @date 2021-05-23 19:51
 */
public abstract class Link extends Item {

    protected String url;

    public Link(String caption, String url) {
        super(caption);
        this.url = url;
    }
}
Tray

Tray表示的是一个含有多个Link类和Tray类的容器。

Tray类使用的add方法将Link类和Tray类集合在一起。

package abstractfactory.factory;

import java.util.ArrayList;

/**
 * @author wenei
 * @date 2021-05-23 19:52
 */
public abstract class Tray extends Item {

    protected ArrayList<Item> tray = new ArrayList<>();

    public Tray(String caption) {
        super(caption);
    }

    public void add(Item item) {
        tray.add(item);
    }
}
Page

Page类是抽象地表示HTML页面的类。

如果将Link和Tray比喻成抽象的“零件”,那么Page类就是抽象的“产品”。

package abstractfactory.factory;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;

/**
 * @author wenei
 * @date 2021-05-23 19:55
 */
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 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();
}
Factory

Factory是生成具体工厂实例的类。

虽然getFactory方法生成的是具体工厂的实例,但是返回值的类型是抽象工厂类型。

createLink、createTray、createPage等方法是用于在抽象工厂中生成零件和产品的方法。

package abstractfactory.factory;

/**
 * @author wenei
 * @date 2021-05-23 20:01
 */
public abstract class Factory {

    public static Factory getFactory(Class<?> clazz) {
        Factory factory = null;
        try {
            factory = (Factory) clazz.newInstance();
        } catch (IllegalAccessException | InstantiationException 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);
}

listfactory包

具体的抽象类实现的包。

ListLink

ListLink类是Link类的子类。

package abstractfactory.listfactory;

import abstractfactory.factory.Link;

/**
 * @author wenei
 * @date 2021-05-23 20:08
 */
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";
    }
}
LinkTray
package abstractfactory.listfactory;

import abstractfactory.factory.Item;
import abstractfactory.factory.Tray;

import java.util.Iterator;

/**
 * @author wenei
 * @date 2021-05-23 20:10
 */
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).append("\n");
        buffer.append("<ul>\n");
        // 遍历Tray中的所有组件
        for (Item item : tray) {
            buffer.append(item.makeHTML());
        }
        buffer.append("</ul>\n");
        buffer.append("</li>\n");
        return buffer.toString();
    }
}
ListPage
package abstractfactory.listfactory;

import abstractfactory.factory.Item;
import abstractfactory.factory.Page;

import java.util.Iterator;

/**
 * @author wenei
 * @date 2021-05-24 11:31
 */
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>");
        buffer.append("<hl>" + title + "</hl>\n");
        buffer.append("<ul>\n");
        Iterator<Item> it = content.iterator();
        while (it.hasNext()) {
            Item item = it.next();
            buffer.append(item.makeHTML());
        }
        buffer.append("</ul>\n");
        buffer.append("<hr><address>" + author + "</address>");
        buffer.append("</body></html>\n");
        return buffer.toString();
    }
}
ListFactory
package abstractfactory.listfactory;

import abstractfactory.factory.Factory;
import abstractfactory.factory.Link;
import abstractfactory.factory.Page;
import abstractfactory.factory.Tray;

/**
 * @author wenei
 * @date 2021-05-24 11:36
 */
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);
    }
}

测试类Test

Main类使用抽象工厂生产零件并将零件组装成产品。

该类并没有使用任何具体零件、产品和工厂。

package abstractfactory;

import abstractfactory.factory.Factory;
import abstractfactory.listfactory.ListFactory;
import abstractfactory.factory.Link;
import abstractfactory.factory.Page;
import abstractfactory.factory.Tray;

/**
 * @author wenei
 * @date 2021-05-24 11:36
 */
public class Test {

    public static void main(String[] args) {
        Factory factory = Factory.getFactory(ListFactory.class);

        Link people = factory.createLink("人民日报", "http://www.people.com.cn/");
        Link gmw = factory.createLink("光明日报", "http://www.gmw.cn/");

        Link us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
        Link jp_yahoo = factory.createLink("Yahoo!Japan", "http://www.yahoo.co.jp/");

        // 日报类链接
        Tray traynews = factory.createTray("日报");
        traynews.add(people);
        traynews.add(gmw);

        // 搜索类链接
        Tray trayyahoo = factory.createTray("Yahoo!");
        trayyahoo.add(us_yahoo);
        trayyahoo.add(jp_yahoo);

        // 创建一个页面
        Page page = factory.createPage("LinkPage", "浩浩");
        // 添加tray
        page.add(traynews);
        page.add(trayyahoo);
        // 将页面输出
        page.output();
    }
}

相关角色

  • AbstractProduct(抽象产品)
    AbstractProduct角色负责定义AbstractFactory角色所生成的抽象零件和产品的接口(API)。在实例程序中,由Link类、Tray类和Page类扮演此角色

  • AbstractFactory(抽象工厂)
    AbstractFactory角色负责定义用于生成抽象产品的接口(API)。在实例程序中,由Factory类扮演此角色。

  • Client(委托者)
    Client仅会调用AbstractFactory角色和AbstractProduct角色的接口(API)来进行工作,对于具体的零件、产品和工厂一无所知。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥牛火锅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值