字面意思:抽象工厂,抽象工厂的工作是将抽象零件组装成抽象产品。
抽象零件:Item类:
抽象零件类,定义抽象方法。
public abstract class Item {protected String caption;public Item(String caption) {this.caption = caption;}public abstract String makeHTML();}
抽象的零件:Link类:
继承了Item类,将自己和Item相关联,自己只储存url链接,caption放在Item中。
public abstract class Link extends Item {protected String url;public Link(String caption,String url) {super(caption);this.url = url;}}
抽象的零件:Tray类:
代表一个托盘,包含多个Link类和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);}}
抽象的产品:Page类:
将Link和Tray比喻成抽象的“零件”,那么Page类就是抽象的产品。可以使用add方法向页面中增加Item(Link或Tray)。
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";FileWriter writer = new FileWriter(fileName);writer.write(this.makeHTML());writer.close();System.out.println(fileName+"编写完成");} catch (IOException e) {e.printStackTrace();}}public abstract String makeHTML();}
抽象的工厂:Factory类:
getFactory方法可以根据指定的类名生成具体工厂的实例。将参数className指定为具体工厂的类名所对应的字符串。可以通过调用Class类的forName方法来动态的读取类信息,接着使用newInstance方法生成该类的实例,并将其作为返回值返回给调用者。
public abstract class Factory {public static Factory getFactory(String className){Factory factory = null;try {factory = (Factory)Class.forName(className).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return factory;}public abstract Link createLinks(String caption,String url);public abstract Tray createTray(String caption);public abstract Page createPage(String title,String author);}
使用工厂将零件组装成为产品:Main类
在Main类中使用抽象工厂生产零件并将零件组装成产品。
public class Main {public static void main(String[] args) {if (args.length != 1) {System.out.println("Usage:java Main class.name.of.ConcreteFactory");System.out.println("Example 1: java Main listFactory.ListFactory");System.exit(0);}Factory factory = Factory.getFactory(args[0]);Link people = factory.createLinks("人民日报","http://www.people.com.cn/");Link gmw = factory.createLinks("光明日报", "http://www.people.com.cn/");Link us_yahoo = factory.createLinks("Yahoo!", "http://www.yahoo.com/");Link jp_yahoo = factory.createLinks("Yahoo!Japan", "http://www.yahoo.co.jp/");Link excite = factory.createLinks("Excite", "http://www.excite.com/");Link google = factory.createLinks("Google", "http://www.google.com/");Tray trayNews = factory.createTray("日报");trayNews.add(people);trayNews.add(gmw);Tray trayYahoo = factory.createTray("Yahoo!");trayYahoo.add(us_yahoo);trayYahoo.add(jp_yahoo);Tray traySearch = factory.createTray("检索引擎");traySearch.add(trayYahoo);traySearch.add(excite);traySearch.add(google);Page page = factory.createPage("LinkPage", "杨文轩");page.add(trayNews);page.add(traySearch);page.output();}}
具体的工厂:ListFactory类
工厂的实现类。
public class ListFactory extends Factory{@Overridepublic Link createLinks(String caption, String url) {return new ListLink( caption, url);}@Overridepublic Tray createTray(String caption) {return new ListTray(caption);}@Overridepublic Page createPage(String title, String author) {return new ListPage(title,author);}}
具体的零件:ListLink类
public class ListLink extends Link{public ListLink(String caption, String url) {super(caption, url);}@Overridepublic String makeHTML() {return "listLink"+url+caption;}}
具体的零件:ListTray类
public class ListTray extends Tray{public ListTray( String author) {super(author);}@Overridepublic String makeHTML() {return "ListTray"+caption;}}
具体的零件:ListPage类
public class ListPage extends Page{public ListPage(String title, String author) {super(title, author);}@Overridepublic String makeHTML() {return "ListPage"+title+author;}}
Abstract Factory模式中的登场角色:
AbstractProduct(抽象产品):
主要负责定义AbstractFactory角色中所生成的抽象零件和产品的接口。上述中的Link类、Tray类、Page类扮演这个角色。
AbstractFactory(抽象工厂):
主要负责定义用于生成抽象产品的接口;在示例程序中,由Factory扮演这个角色。调用抽象产品
Client(委托者):
仅仅会调用抽象工厂和抽象产品的接口来进行工作,对具体的零件、产品和工厂一无所知。
ConcreteProduct(具体产品):
ConcreteFactory(具体工厂):
负责实现抽象工厂的接口。实现抽象工厂中的抽象方法,调用具体的产品。
思路:
易于增加具体的工厂:
在Abstract Factory模式中增加具体的工厂是非常容易的,假设需要在示例程序中增加新的具体工厂,那么需要做的仅仅是编写抽象产品的子类,并实现抽象工厂中定义的抽象方法。也就是只需要将抽象部分具体化即可,不需要修改已有的代码部分,非常优雅。
难以增加新的零件:
如果需要在Abstract Factory模式中增加新的零件时会怎么样?需要对所有的具体工厂进行相应的修改才行。已经编写完成的具体工厂越多,需要做的修改就越多。
相关的设计模式:
Builder模式:
Builder模式是分阶段地制作复杂实例,而Abstract Factory则是通过调用抽象产品的接口来组装抽象产品,生成具有复杂结构的实例。
Factory Method模式:
有时Abstract Factory模式中零件和产品的生成会使用到Factory Method模式。
Composite模式:
有时Abstract Factory模式在制作产品时会使用Composite模式。
Singleton模式:
有时Abstract Factory模式在制作产品时会使用Singleton模式。
问题:
将子类设置为protected,子类可以访问该字段,但是如果修改为private,会存在哪些优缺点呢?
设置为private的优点:
- 方法更加安全;- 子类不会依赖于父类字段的实现。
缺点:
- 必须编写一些方法让外部可以访问自身的字段属性。
