设计模式(Java)—Abstract Factory模式

抽象工厂的工作是将“抽象零件”组装为“抽象产品”。
在Abstract Factory模式中将会出现抽象工厂,它将会抽象零件组装为抽象产品。也就是说人们并不关心零件的具体实现,而只关心接口,我们仅使用该接口将零件组装成为产品。
在Tempate Method模式和Builder模式中,子层这一层负责方法的具体实现,在Abstract Factory模式也是一样的。在子类这一层中有具体的工厂,它负责将具体的零件组装成为具体的产品。

示例程序:将带有层次关系的链接集合制作成HTML文件。
设计模式(Java)—Abstract Factory模式_第1张图片

设计模式(Java)—Abstract Factory模式_第2张图片

抽象的零件类:Item类
Item类是Link类和Tray类的父类,这样Link类和Tray类就具有可替换性了,makeHTML方法是抽象方法。

package AbstractFactory;
//零件抽象类,构造函数,抽象方法
public abstract class Item {
    protected String caption;
    public Item(String caption) {
        // TODO Auto-generated constructor stub
        this.caption = caption;
    }
    public abstract String makeHTML();
}

抽象的零件:Link类,是抽象的表示HTML的超链接的类。
URL字段中保存的是超链接所指向的地址,Link类并没有实现父类中的抽象方法,所以它还是一个抽象类。

package AbstractFactory;

//零件的抽象类,初始化
public abstract class Link extends Item {
    protected String url;

    public Link(String caption,String url) {
        super(caption);
        // TODO Auto-generated constructor stub
        this.url = url;
    }
}

抽象的零件:Tray类,是表示一个含有多个Link类和Tray类的容器,使用add()方法把Link类和Tray类集合在一起。

package AbstractFactory;

import java.util.ArrayList;

//零件的抽象类,初始化
public abstract class Tray extends Item {
    protected ArrayList tray = new ArrayList();

    public Tray(String caption) {
        super(caption);
        // TODO Auto-generated constructor stub
    }

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

}

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

package AbstractFactory;

import java.io.FileWriter;
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) {
        // TODO Auto-generated constructor stub
        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 (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
    public abstract String makeHTML();

}

抽象的工厂:Factory类,其中的getFactory方法可以根据类的全名利用反射机制生成具体工厂的实例,getFactory方法通过调用class类的forName方法来动态地读取类信息,接着使用newInstance方法生成该类的实例,并将其作为返回值返回给调用者。

package AbstractFactory;

//抽象工厂类,其中通过反射机制利用参数传进来的包全名实例化类获得具体工厂类实例
public abstract class Factory {
    public static Factory getFactory(String classname) {
        Factory factory = null;
        try {
            factory = (Factory)Class.forName(classname).newInstance();

        }catch (ClassNotFoundException e) {
            // TODO: handle exception
            System.err.println("没有找到"+classname+"类");
        }catch (Exception e) {
            // TODO: handle exception
            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);
}

使用工厂将零件组装成为产品:Main类,该类没有使用任何具体的零件、产品和工厂。具体工厂的类名是通过命令行或给main主函数传入参数来指定的。

package AbstractFactory;

public class Main {
//通过主程序参数控制具体工厂类型
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        if(args.length!=1){
            System.out.println("Usage:java Main class.name.of.ConcreteFactory");
            System.out.println("Example 1:java Main listfactory.ListFactory");
            System.out.println("Example 2:java Main tablefactory.ListFactory");
            System.exit(0);
        }
        //反射机制需要类的全名(带包名)
        Factory factory = Factory.getFactory("AbstractFactory."+args[0]);


        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/");
        Link google = factory.createLink("Google", "http://www.google.com/");

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

        Tray traysearch = factory.createTray("检索引擎");
        traysearch.add(us_yahoo);
        traysearch.add(jp_yahoo);
        traysearch.add(google);

        Page page = factory.createPage("LinkPage", "李佳琪");
        page.add(traynews);
        page.add(traysearch);
        page.output();

    }

}

具体的工厂:ListFactory类,实现了Factory类的createLink方法、createTray方法、createPage方法。

package AbstractFactory;

//具体工厂类,如何配置零件
public class ListFactory extends Factory {

    @Override
    public Link createLink(String caption, String url) {
        // TODO Auto-generated method stub
        return new ListLink(caption,url);
    }

    @Override
    public Tray createTray(String caption) {
        // TODO Auto-generated method stub
        return new ListTray(caption);
    }

    @Override
    public Page createPage(String title, String author) {
        // TODO Auto-generated method stub
        return new ListPage(title,author);
    }

}

具体的零件:ListLink类

package AbstractFactory;

public class ListLink extends Link {
//零件的具体类,继承抽象,实现其中的抽象方法
    public ListLink(String caption, String url) {
        super(caption, url);
        // TODO Auto-generated constructor stub
    }

    @Override
    public String makeHTML() {
        // TODO Auto-generated method stub
        return "
  • +url+"\">"+caption+"
  • \n"
    ; } }

    具体的零件:ListTray类

    package AbstractFactory;
    
    import java.util.Iterator;
    //零件的具体类,继承抽象,实现其中的抽象方法
    public class ListTray extends Tray {
    
        public ListTray(String caption) {
            super(caption);
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public String makeHTML() {
            // TODO Auto-generated method stub
            StringBuffer buffer = new StringBuffer();
            buffer.append("
  • \n"); buffer.append(caption+"\n"); buffer.append("
      \n"); Iterator it = tray.iterator(); while (it.hasNext()) { Item item = (Item)it.next(); buffer.append(item.makeHTML()); } buffer.append("
    \n"
    ); buffer.append("
  • \n"
    ); return buffer.toString(); } }

    具体的产品:ListPage类

    package AbstractFactory;
    
    import java.util.Iterator;
    //零件的具体类,继承抽象,实现其中的抽象方法,Buffer存储html页面内容
    public class ListPage extends Page {
    
        public ListPage(String title, String author) {
            super(title, author);
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public String makeHTML() {
            // TODO Auto-generated method stub
            StringBuffer buffer = new StringBuffer();
            buffer.append(""</span>+title+<span class="hljs-string">"\n");
            buffer.append("");
            buffer.append("

    "+title+""); buffer.append("
      \n"); Iterator it = content.iterator(); while (it.hasNext()) { Item item = (Item)it.next(); buffer.append(item.makeHTML()); } buffer.append("
    \n"
    ); buffer.append("
    "
    +author+""); buffer.append("\n"); return buffer.toString(); } }

    设计模式(Java)—Abstract Factory模式_第3张图片

    Abstract Factory模式中的角色:
    AbstractProduct(抽象产品)
    AbstractProduct角色负责定义Abstract Factory角色所生成的抽象零件和产品的接口,在示例中,由Linke类、Tray类、Page类扮演此角色。

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

    Client(委托者)
    Client角色仅会调用AbstractFactory角色和AbstractProduct角色的接口来进行工作,对于具体的零件、产品、工厂一无所知。在示例中,由Main类扮演此角色。

    ConcreteProduct(具体产品)
    ConcreteProduct角色负责实现AbstractProduct接口

    ConcreteFactory
    ConcreteFactory角色负责实现AbstractFactory角色的接口

    你可能感兴趣的:(Java)