zoukankan      html  css  js  c++  java
  • 一天一个设计模式——Abstract Factory抽象工厂模式

    一、模式说明

      前面学习了工厂方法(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();
    }
    View Code

    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;
        }
    }
    View Code

    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);
        }
    }
    View Code

    同样的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();
    }
    View Code

    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);
    }
    View Code

    该类中使用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);
        }
    }
    View Code

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

    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>
    ");
            buffer.append(caption + "
    ");
            buffer.append("<ul>
    ");
            Iterator iterator = tray.iterator();
            while(iterator.hasNext()){
                Item item = (Item) iterator.next();
                buffer.append(item.makeHtml());
            }
            buffer.append("</ul>
    ");
            buffer.append("</li>
    ");
            return buffer.toString();
        }
    }
    View Code

    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>
    ");
            buffer.append("<body>
    ");
            buffer.append("<h1>" + title + "</h1>
    ");
            buffer.append("<ul>
    ");
            Iterator iterator = content.iterator();
            while(iterator.hasNext()){
                Item item = (Item)iterator.next();
                buffer.append(item.makeHtml());
            }
            buffer.append("</ul>
    ");
            buffer.append("<hr><address>" + author + "</address>");
            buffer.append("</body></html>
    ");
            return buffer.toString();
        }
    }
    View Code

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

    四、模式中的角色

    • 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中也是有用到的,所以需要好好消化一下。

  • 相关阅读:
    第十章 系统级I/O
    第九章 虚拟内存
    第六章 存储器层次结构
    第八章 异常控制流(下)
    第八章 异常控制流(上)
    第三章 机器的程序级表示(下)
    第三章 机器的程序级表示(中)
    第三章 机器的程序级表示(上)
    python学习之列表的定义以及增删改查
    Python学习之字符串中的下标和切片以及逆序
  • 原文地址:https://www.cnblogs.com/zheng-hong-bo/p/11105362.html
Copyright © 2011-2022 走看看