設計模式-抽象工廠(Abstract Factory)

2018-1-21 by Atlas


  • 設計思想

客戶類和工廠類分開。消費者任何時候需要某套產品集合時,只需向抽象工廠請求即可。抽象工廠會再向具體的工廠生產出符合產品集規格的產品。

  • 應用場景

抽象替代具體,降低客戶方對具體工廠的耦合,只給客戶方提供接口和抽象類。
優點:降低依賴具體,降低耦合。
缺點:完工的工廠越多,新增其他零件需要的修改就越多。

  • UML 類圖

抽象工廠 UML

  • AbstractProduct(抽象產品)參與者
    AbstractProduct參與者規定由AbstractFactory參與者所產生的抽象零件和產品的接口。
  • AbstractFactory(抽象工廠)參與者
    AbstractFactory參與者規定用來產生AbstractProduct參與者的對象實例的接口。
  • Client(客戶)參與者
    Client參與者是一個只使用AbstractFactory參與者和AbstractProduct參與者的接口來完成工作的參與者。Client參與者並不知道具體零件、產品和工廠。
  • ConcreteProduct(具體產品)參與者
    ConcreteProduct參與者是AbstractProduct參與者的具體實現。
  • ConcreteFactory(具體工廠)參與者
    ConcreteFactory參與者是AbstractFactory參與者的具體實現。
  • 標準示例
public abstract class Item {
    protected String caption;
    public Item(String caption){
        this.caption = caption;
    }
    public abstract String makeHTML();
}
public abstract class Link extends Item {
    protected String url;
    public Link(String caption, String url){
        super(caption);
        this.url = url;
    }
}
public abstract class Tray extends Item {
    protected Vector tray = new Vector();
    public Tray(String caption){
        super(caption);
    }
    public void add(Item item){
        tray.add(item);
    }
}
public abstract class Page {
    protected String title;
    protected String autor;
    protected Vector content = new Vector();
    public Page(String title, String autor){
        this.title = title;
        this.autor = autor;
    }
    public void add(Item item){
        content.add(item);
    }
    public abstract String makeHTML();
    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 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 ex){
            ex.printStackTrace();
        }
        return factory;
    }
    public abstract Link createLink(String caption, String url);
    public abstract Tray createTray(String caption);
    public abstract Page createPage(String title, String autor);
}

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";
    }
}
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).append("\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();
    }
}
public class ListPage extends Page {
    public ListPage(String title, String autor){
        super(title, autor);
    }
    @Override
    public String makeHTML() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<html><head><title>").append(title).append("</title></head>\n");
        buffer.append("<body>\n");
        buffer.append("<h1>").append(title).append("</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>").append(autor).append("</address>");
        buffer.append("</body><html>\n");
        return buffer.toString();
    }
}

public class ListFactory extends Factory {
    @Override
    public Link createLink(String caption, String url) {
        return new ListLink(caption, url);
    }
    @Override
    public Tray createTray(String caption) {
        return new ListTray(caption);
    }
    @Override
    public Page createPage(String title, String autor) {
        return new ListPage(title, autor);
    }
}

public class Main {
    public static void main(String[] args){
        Scanner scanner=new Scanner(System.in);
        String className = scanner.next();
        Factory factory = Factory.getFactory(className);
        Link asahi = factory.createLink("朝日新聞", "http://www.asahi.com/");
        Link yomiuri = factory.createLink("讀賣新聞", "http://www.yomiuri.co.jp/");
        Link us_yahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
        Link google = factory.createLink("Google", "http://www.google.com/");
        Tray trayews = factory.createTray("新聞");
        trayews.add(asahi);
        trayews.add(yomiuri);
        Tray trayyahoo = factory.createTray("Yahoo!");
        trayyahoo.add(us_yahoo);
        Tray traysearch = factory.createTray("搜索引擎");
        traysearch.add(google);
        Page page = factory.createPage("LinkPage", "Atlas");
        page.add(trayews);
        page.add(trayyahoo);
        page.add(traysearch);
        page.output();
    }
}

抽象產品參與者是Link類、Tray類和Page類。
抽象工廠參與者是Factory類。
具體產品參與者是ListLink類、ListTray類和ListPage類。
具體工廠參與者是ListFactory類。

  • 案例鑑賞

搜尋中...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章