1、模式說明html
前面學習了工廠方法(Factory Method)模式。在工廠方法模式中,在工廠方法模式中,父類決定如何生成實例,但並不決定所要生成的具體類,具體的處理交由子類來處理。這裏學習的抽象工廠方法模式中,抽象工廠使用抽象的零件組裝成抽象的產品。即便用包含特定的方法接口零件,將零件組裝成抽象產品。java
2、模式類圖:設計模式
上面的類圖中包含兩個包:包含抽象工廠,抽象零件,抽象產品的類所在的包以及具體工廠實現類的包。app
3、代碼示例ide
一、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是抽象方法,須要在子類中實現。ui
二、Link類:this
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類仍是一個抽象類。google
三、Tray類:url
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類也是抽象類。
四、抽象的產品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(); }
五、抽象工廠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方法是用於在抽象工廠中生成抽象零件和產品的抽象方法,具體的實現交由子類,不過在這裏肯定了方法的名字和簽名。
看完了模式的抽象類,接下來看具體的實現類:
一、具體的工廠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); } }
二、具體的零件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"; } }
三、具體的零件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(); } }
四、具體的零件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(); } }
五、運行結果:
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(); } }
4、模式中的角色
5、抽象工廠模式的特色
6、相關的設計模式
最後,抽象工廠模式在Spring中也是有用到的,因此須要好好消化一下。