每日学一个设计模式8——抽象工厂模式

本文介绍了抽象工厂模式,用于创建复杂对象,其核心在于将关联零件组成产品。文章详细阐述了模式的角色:抽象产品、抽象工厂、委托者、具体产品和具体工厂,并通过一个网页制作的例子展示了其实现。同时,文章讨论了如何扩展产品簇和产品线,指出抽象工厂模式适合扩展产品簇,而不适合扩展产品线。
摘要由CSDN通过智能技术生成

抽象工厂模式(将关联零件组成产品)

用处

将“抽象零件”组装为“抽象产品”(创建复杂对象)

角色

  • AbstractProduct(抽象产品)
    该角色负责定义AbstractFactory角色所生成的抽象零件和产品的方法(API)。
  • AbstracFactory(抽象工厂)
    该角色负责定义用于生成抽象产品的方法(API)。
  • Client(委托者)
    该角色仅会调用AbstractFactory角色和AbstractProduct角色的方法(API)来进行工作,对具体的零件、产品、工厂一无所知。
  • ConcreteProduct(具体产品)
    该角色负责实现AbstractProduct角色负责的方法(API)
  • ConcreteFactory(具体工厂)
    该角色负责实现AbstractFactory角色的方法(API)

类图

在这里插入图片描述
类图比较复杂,总结以下几点

  • 分为抽象工厂和具体工厂两个模块
  • 抽象工厂模块中,定义了一个抽象工厂类,在其中定义了创建产品的抽象方法,每个抽象产品有自己的抽象方法。
  • 在具体工厂模块中,定义了一个具体工厂类,继承抽象工厂类并重写了方法,用于获取具体产品,每个具体产品都继承了对应抽象类并重写了抽象方法

举例

package 设计模式.创建型模式.工厂模式.抽象工厂模式;

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

public class Main {
    public static void main(String[] args) {
        Factory factory = Factory.getFactory("设计模式.创建型模式.工厂模式.抽象工厂模式.ListFactory");
        Link people = factory.createLink("人民日报","http://www.people.com.cn/");
        Link gmw = factory.createLink("光明日报","http://www.gmw.cn/");

        Tray traynews = factory.createTray("日报");
        traynews.add(people);
        traynews.add(gmw);

        Page page = factory.createPage("LinkPage","杨文轩");
        page.add(traynews);

        page.output();
    }

}

abstract class Item{
    protected String caption;
    public Item(String caption){
        this.caption = caption;
    }
    public abstract String makeHTML();
}
//AbstractProduct角色
abstract class Link extends Item{
    protected String url;
    public Link(String caption,String url){
        super(caption);
        this.url = url;

    }
    public abstract  String makeHTML();
}
//AbstractProduct角色
abstract class Tray extends Item{
    protected ArrayList tray = new ArrayList();
    protected String caption;
    public Tray(String caption){
       super(caption);
    }
    public void add(Item item){
        tray.add(item);
    }
}


//AbstractProduct角色
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();
}


//AbstractFactory角色
abstract class Factory{
    public static Factory getFactory(String classname){
        Factory factory = null;
        try{
            factory = (Factory)Class.forName(classname).newInstance();
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }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);

}


//ConcreteFactory角色
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);
    }
}

//ConcreteProduct角色
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";
    }
}
//ConcreteProduct角色
class ListTray extends Tray{
    public ListTray(String caption){
        super(caption);
    }
    public String makeHTML(){
        StringBuffer buffer = new StringBuffer();
        buffer.append("<li>\n");
        buffer.append(caption+"\n");
        buffer.append("<ul>\n");
        Iterator it = tray.iterator();
        while(it.hasNext()){
            Item item = (Item)it.next();
            buffer.append(item.makeHTML());
        }
        buffer.append("</ul>\n");
        buffer.append("</li>\n");
        return buffer.toString();
    }
}
//ConcreteProduct角色
class ListPage extends Page{
    public ListPage(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("<ul>\n");
        Iterator it = content.iterator();
        while(it.hasNext()){
            Item 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();
    }
}

如果想要新增生产其他产品的工厂,只需要写一个新的具体工厂,及其所要生产的具体产品类即可。本例中是一个新的具体工厂和继承Link,Tray,Page的子类。

总结

  • 用于创建复杂对象
  • 抽象工厂模式易于增加工厂(只需要增加类,不需要改写好的代码,符合开闭原则),而难以增加新的产品(违反开闭原则)。

基于上述特性,引入一个产品簇产品线的概念

  • 产品簇指具有相同或相似的功能结构或性能,共享主要的产品特征、组件或子结构,并通过变型配置来满足特定市场的一组产品的聚类,举例:苹果手机,华为手机,小米手机,属于同一产品簇
  • 产品线是指一群相关的产品,举例:苹果手机,苹果电脑,苹果平板,属于同一产品线

我们可以看出,假设把每个具体工厂都视作一个品牌,那么可以发现由于易于增加工厂的特性,抽象工厂模式适合扩展产品簇,而又因为难以增加新的产品的特性,抽象工厂模式不适合扩展产品线。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黑白程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值