LoginSignup
0
0

More than 3 years have passed since last update.

AbstractFactoryパターン

Last updated at Posted at 2020-09-04

AbstractFactoryパターンとは

抽象的な部品を組み合わせて抽象的な製品を作る。
部品の具体的な実装には注目せず、インターフェース(API)に注目する。
そして、そのインターフェース(API)だけを使って部品を組み立て、製品をまとめる。

AbstractProduct(抽象的な製品)の役

AbstractProduct役はAbstractFactory役によって作り出される抽象的な部品や製品のインターフェースを定める。

package factory;

/**
 * HTMLのハイパーリンクを抽象的に表現したクラス
 *
 */
public abstract class Link extends Item{
    // リンクの飛び先のURL保持用
    protected String url;

     public Link(String caption, String url) {
         super(caption);
         this.url = url;
    }
}
package factory;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;

/**
 * HTMLページ全体を抽象的に表現したクラス
 *
 */
public abstract class Page {
    protected String title;
    protected String author;
    protected ArrayList<Item> 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();
}
package factory;

import java.util.ArrayList;
/**
 * 複数のLinkやTrayを集めてひとまとまりにしたものを表すクラス
 *
 */
public abstract class Tray extends Item{
    protected ArrayList<Item> tray = new ArrayList<>();

     public Tray(String caption) {
         super(caption);
    }

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

AbstractFactory(抽象的な工場)の役

AbstractFactory役はAbstractProduct役のインスタンスを作り出すためのインターフェースを定める。

package factory;

/**
 * クラス名を指定して具体的な工場のインスタンを作成するクラス
 *
 */
public abstract class Factory {
    public static Factory getFactory(String className) {
        Factory factory = null;
        try {
            factory = (Factory)Class.forName(className).newInstance();
        } catch (ClassCastException e) {
            System.out.println("クラス " + className + "が見つかりません。");
        } catch (Exception 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);

}

Client(依頼者)の役

Client役はAbstractFactory役とAbstractProduct役のインターフェースだけを使って仕事を行う役。
Client役は具体的な部品や製品や工場については知らない。

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class Main {

    public static void main(String[] args) {

        if (args.length != 1) {
            System.out.println("Usage: java Main class.mame.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 asahi = factory.createLink("朝日新聞", "http://www.asahi.com/");
        Link yomiuri = factory.createLink("読売新聞", "http://www.yomiuri.co.jp/");

        Link usYahoo = factory.createLink("Yahoo!", "http://www.yahoo.com/");
        Link jpYahoo = factory.createLink("Yahoo!Japan", "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("新聞");
        trayNews.add(asahi);
        trayNews.add(yomiuri);

        Tray trayYahoo = factory.createTray("Yahoo!");
        trayYahoo.add(usYahoo);
        trayYahoo.add(jpYahoo);

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

}

ConcreteProduct(具体的な製品)の役

ConcteteProduct役ではAbstract役のインターフェース(API)を実装する。

package listFactory;

import factory.Link;

public class ListLink extends Link{

    public ListLink(String caption, String url) {
        super(caption, url);
    }

    public String makeHtml() {
        return " <li><a href=\"" + url + "\">" + caption + "</a></li>\n";
    }

}
package listFactory;

import java.util.Iterator;

import factory.Item;
import factory.Page;

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<Item> it = content.iterator();
        while (it.hasNext()) {
            Item item = it.next();
            buffer.append(item.makeHtml());
        }
        buffer.append("</ul>\n");
        buffer.append("<hr><address>" + author + "</address>");
        buffer.append("</body></html>\n");
        return buffer.toString();
    }
}
package listFactory;

import java.util.Iterator;

import factory.Item;
import factory.Tray;

public class ListTray extends Tray {

    public ListTray(String caption) {
        super(caption);
    }

    public String makeHtml() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<li>\n");
        buffer.append(caption + "\n");
        buffer.append("<ul>\n");
        Iterator<Item> it = tray.iterator();
        while (it.hasNext()) {
            Item item = it.next();
            buffer.append(item.makeHtml());
        }
        buffer.append("</ul>\n");
        buffer.append("</li>\n");
        return buffer.toString();
    }
}

ConcreteFactory(具体的な工場)の役

ConcreteFactory役ではAbstractFactory役のインターフェース(API)を定める。

package listFactory;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

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 author) {
        return new ListPage(title, author);
    }
}

引数でtableFactory.TableFactoryを渡して実行して作成されたhtmlファイル

スクリーンショット 2020-09-04 15.50.31.png

別の具体的な工場を追加する

工場を追加するのは簡単であった。
どのようなクラスを作り、どのようなメソッドを実装すれば良いかが明確なため。

package tableFactory;

import factory.Link;

public class TableLink extends Link {

    public TableLink(String caption, String url) {
        super(caption, url);
    }

    @Override
    public String makeHtml() {
        return "<td><a href=\"" + url + "\">" + caption + "</a></td>\n";
    }
}
package tableFactory;

import java.util.Iterator;

import factory.Item;
import factory.Page;

public class TablePage extends Page {

    public TablePage(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("<table width=\"80%\" border=\"3\">\n");
        Iterator<Item> it = content.iterator();
        while (it.hasNext()) {
            Item item = it.next();
            buffer.append("<tr>" + item.makeHtml() + "</tr>");
        }
        buffer.append("</table>\n");
        buffer.append("<hr><address>" + author + "</address>");
        buffer.append("</body></html>\n");
        return buffer.toString();
    }
}
package tableFactory;

import java.util.Iterator;

import factory.Item;
import factory.Tray;

public class TableTray extends Tray {

    public TableTray(String caption) {
        super(caption);
    }

    @Override
    public String makeHtml() {
        StringBuffer buffer = new StringBuffer();
        buffer.append("<td>");
        buffer.append("<table width=\"100%\" border=\"1\"><tr>");
        buffer.append("<td bgcolor=\"#cccccc\" align=\"center\" colspan=\"" + tray.size() + "\"><b>" + caption + "</b></td>");
        buffer.append("</tr>\n");
        buffer.append("<tr>\n");
        Iterator<Item> it = tray.iterator();
        while (it.hasNext()) {
            Item item = it.next();
            buffer.append(item.makeHtml());
        }
        buffer.append("</tr></table>");
        buffer.append("</td>");
        return buffer.toString();
    }
}
package tableFactory;

import factory.Factory;
import factory.Link;
import factory.Page;
import factory.Tray;

public class TableFactory extends Factory {

    @Override
    public Link createLink(String caption, String url) {
        return new TableLink(caption, url);
    }

    @Override
    public Tray createTray(String caption) {
        return new TableTray(caption);
    }

    @Override
    public Page createPage(String title, String author) {
        return new TablePage(title, author);
    }
}

Client役であるMainは全く変更せず、実行時の引数をtableFactory.TableFactoryにして実行して作成されたhtmlファイル

スクリーンショット 2020-09-04 15.57.57.png

こちらを参考にさせていただきました。
増補改訂版Java言語で学ぶデザインパターン入門

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0