Abstract Factoryパターン
インスタンスの生成を専門に行う抽象クラスを用意する
Abstract Factory パターンとは、インスタンスの生成を専門に行う抽象クラスを用意することで、整合性を必要とされる一連のオブジェクト群を間違いなく生成するパターンです。

例えば、街の中でタクシーに乗ることを考えて見ましょう。まず、屋根に何かが乗っかっている自動車を探しますね。そして、それが近づいてきてタクシーと確認できたら、空車であることを確認して手を挙げますね。これは、A社のタクシーだからこうして、B社だからこうして、というように方法を変えることはありません。どの会社のタクシーでも同じ手順で行います。
つまり、 A社だからB社だからではなく、タクシーという抽象概念に対して一連の手順を行っているわけです。
データベースを使用する例を挙げてみましょう。
たとえば、DBMSであるSQL ServerとOracleをシステムによって切り替えられるようにすることを考えて見ましょう。
ひとつには、まったく同じメンバを持つ同名のクラスを2種類用意しておくという案があります。SQL Serverを使用するクラスもOracleを使用するクラスも、どちらも同じDataBaseという名前のクラスにして、まったく同じメンバを持たせるのです。ソースファイルを交換するだけでDBMSを変えられ、プログラムの内容には一切変更が不要です。ただし、見た目だけでは区別しにくいため、取り扱いを誤ってしまう危険性があります。
それなら、メンバは同じでクラス名だけを変えるという案(Template Methodパターン)はどうでしょう。SQL Server用はSqlDataBaseクラス、Oracle用はOracleDataBaseクラスとするのです。取り扱いを誤ることはないでしょうが、DBMSを変更する際に、プログラムの中にあるクラス名(new をするクラス)を変更しなければなりません。いずれも問題があるのです。
Abstract Factory パターンでも、インスタンス生成のところは Factory Method パターンと同じです。ただ Factory Method と違い、Factory クラスは生成のみを専門に受け持ち、自身では状態を持ちません。Factory Method は new する代わりに生成メソッドを追加することであり、Abstract Factory は抽象的な存在(=自身の実体を持たない)を意味しています。
このような生成を専門につかさどるメソッドがあるのは、複数のインスタンスの組を生成するためです。単一のクラスのインスタンスを生成するならそのクラスに create メソッドを作るか、あるいは単に new を行えばいいだけです。Factory Method のように生成メソッドを持っていることが重要なのではなく、生成するインスタンスの組を持っていることがポイントなのです。
そしてこのような Factory クラスを複数作って、状況に応じて生成されるインスタンスの組を切り替えます。
知らないからこそ、入れ替えができるのです。入れ替えられるからこそ、部品としての価値が高くなるのです。この「交換可能性」については、クラスを設計するときに常に意識しておくことが必要になります。
例題
区分ごとの合計値を計算するクラスと、すべての合計値を計算するクラスとを作り、実行時にどちらを使用するかを決められるようにしなさい。
| 引数 sub 区分1 800 | 引数 whole 総合計 1400 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.java public abstract class AbstractTotal {
// 区分 , 数値 (実際には DB などから数値を得る。)
protected Data[] list = new Data[] {
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
};
protected Data[] total; // 合計値
public abstract int getDivision(int n);
public abstract int getTotal(int n);
public abstract AbstractSummary getSummary();
public abstract AbstractDivisionName createDivisionName();
public void operation() {
AbstractSummary sum = getSummary();
total = sum.calculateTotal();
}
}
SubTotal.java public class SubTotal extends AbstractTotal {
public AbstractSummary getSummary() {
return new SubTotalSummary(list);
}
public int getDivision(int n) {
return total[n].no; // 区分
}
public int getTotal(int n) {
return total[n].value; // 合計値
}
public AbstractDivisionName createDivisionName() {
return new SubDivisionName();
}
}
WholeTotal.java public class WholeTotal extends AbstractTotal {
public WholeTotalSummary getSummary() {
return new WholeTotalSummary(list);
}
public int getDivision(int n) {
return total[0].no; // 区分
}
public int getTotal(int n) {
return total[0].value; // 合計値
}
public AbstractDivisionName createDivisionName() {
return new WholeDivisionName();
}
}
Main.java public class Main {
public static void main(String[] args) {
AbstractTotal total = null;
if (args[0].equals("sub"))
total = new SubTotal();
else
total = new WholeTotal();
total.operation();
AbstractDivisionName divisionName = total.createDivisionName();
System.out.println(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0));
}
}
|
Abstract Factoryパターンを使用した例 AbstractTotal.java public abstract class AbstractTotal {
// 区分 , 数値 (実際には DB などから数値を得る。)
protected Data[] list = new Data[] {
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
};
protected Data[] total; // 合計値
public abstract int getDivision(int n);
public abstract int getTotal(int n);
public abstract AbstractSummary getSummary();
public void operation() {
AbstractSummary sum = getSummary();
total = sum.calculateTotal();
}
}
SubTotal.java public class SubTotal extends AbstractTotal {
public AbstractSummary getSummary() {
return new SubTotalSummary(list);
}
public int getDivision(int n) {
return total[n].no; // 区分
}
public int getTotal(int n) {
return total[n].value; // 合計値
}
}
WholeTotal.java public class WholeTotal extends AbstractTotal {
public AbstractSummary getSummary() {
return new WholeTotalSummary(list);
}
public int getDivision(int n) {
return total[0].no; // 区分
}
public int getTotal(int n) {
return total[0].value; // 合計値
}
}
AbstractFactory.java public abstract class AbstractFactory {
public abstract AbstractTotal getTotal();
public abstract AbstractDivisionName getDivisionName();
}
SubFactory.java public class SubFactory extends AbstractFactory {
public AbstractTotal getTotal() {
return new SubTotal();
}
public AbstractDivisionName getDivisionName() {
return new SubDivisionName();
}
}
WholeFactory.java public class WholeFactory extends AbstractFactory {
public AbstractTotal getTotal() {
return new WholeTotal();
}
public AbstractDivisionName getDivisionName() {
return new WholeDivisionName();
}
}
Factory.java public class Factory {
private AbstractFactory factory;
public Factory() {}
public Factory(String c) {
if ("sub".equals(c)) {
factory = new SubFactory();
}
else {
factory = new WholeFactory();
}
}
public AbstractFactory getFactory() {
return factory;
}
}
Main.java public class Main {
public static void main(String[] args) {
AbstractFactory factory = new Factory(args[0]).getFactory();
AbstractTotal total = factory.getTotal();
total.operation();
AbstractDivisionName divisionName = factory.getDivisionName();
System.out.println(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0));
}
}
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.h #include "AbstractSummary.h"
#include "AbstractDivisionName.h"
class AbstractTotal
{
protected:
static Data* list[];
static int size;
Data** total; // 合計値
public:
AbstractTotal(void);
virtual ~AbstractTotal(void);
virtual AbstractSummary* getSummary(void) = 0;
virtual int getDivision(int) = 0;
virtual int getTotal(int) = 0;
virtual AbstractDivisionName* createDivisionName(void) = 0;
void operation(void);
}; AbstractTotal.cpp #include "AbstractTotal.h"
// 区分, 数値(実際にはDB から得る。)
Data* AbstractTotal::list[] = {
new Data(1,100),
new Data(1,500),
new Data(1,200),
new Data(2,400),
new Data(2,200)
};
int AbstractTotal::size = sizeof(list) / sizeof(list[0]);
AbstractTotal::AbstractTotal(void) {}
AbstractTotal::~AbstractTotal(void) {}
void AbstractTotal::operation(void)
{
AbstractSummary* sum = getSummary();
total = sum->calculateTotal();
delete sum;
}
SubTotal.h #include "AbstractTotal.h"
#include "AbstractDivisionName.h"
class SubTotal : public AbstractTotal
{
public:
SubTotal(void);
virtual ~SubTotal(void);
AbstractSummary* getSummary(void);
int getDivision(int);
int getTotal(int);
AbstractDivisionName* createDivisionName(void);
}; SubTotal.cpp #include "SubTotal.h"
#include "SubTotalSummary.h"
#include "SubDivisionName.h"
SubTotal::SubTotal(void) {}
SubTotal::~SubTotal(void) {}
AbstractSummary* SubTotal::getSummary(void) {
return new SubTotalSummary(list, size);
}
int SubTotal::getDivision(int n) {
return total[n]->no; // 区分
}
int SubTotal::getTotal(int n) {
return total[n]->value; // 合計値
}
AbstractDivisionName* SubTotal::createDivisionName(void) {
return new SubDivisionName();
}
WholeTotal.h #include "AbstractTotal.h"
#include "AbstractDivisionName.h"
class WholeTotal : public AbstractTotal
{
public:
WholeTotal(void);
virtual ~WholeTotal(void);
AbstractSummary* getSummary();
int getDivision(int);
int getTotal(int);
AbstractDivisionName* createDivisionName(void);
}; WholeTotal.cpp #include "WholeTotal.h"
#include "WholeTotalSummary.h"
#include "WholeDivisionName.h"
WholeTotal::WholeTotal(void) {}
WholeTotal::~WholeTotal(void) {}
AbstractSummary* WholeTotal::getSummary(void) {
return new WholeTotalSummary(list, size);
}
int WholeTotal::getDivision(int n) {
return total[0]->no; // 区分
}
int WholeTotal::getTotal(int n) {
return total[0]->value; // 合計値
}
AbstractDivisionName* WholeTotal::createDivisionName(void) {
return new WholeDivisionName();
}
main.cpp #include <iostream>
using namespace std;
#include "SubTotal.h"
#include "WholeTotal.h"
#include "AbstractDivisionName.h"
int main(int argc, char* argv[]) {
AbstractTotal* total;
if (strcmp("sub", argv[1]) == 0)
total = new SubTotal();
else
total = new WholeTotal();
total->operation(); // 区分ごとの合計値計算
AbstractDivisionName* divisionName = total->createDivisionName();
cout << divisionName->getName(total->getDivision(0))
<< " " << total->getTotal(0) << endl; // 合計値
delete divisionName;
delete total;
return 0;
}
|
Abstract Factoryパターンを使用した例 AbstractTotal.h #include "AbstractSummary.h"
#include "AbstractDivisionName.h"
class AbstractTotal
{
protected:
static Data* list[];
static int size;
Data** total; // 合計値
public:
AbstractTotal(void);
virtual ~AbstractTotal(void);
virtual AbstractSummary* getSummary(void) = 0;
virtual int getDivision(int) = 0;
virtual int getTotal(int) = 0;
void operation(void);
}; AbstractTotal.cpp #include "AbstractTotal.h"
// 区分, 数値(実際にはDB から得る。)
Data* AbstractTotal::list[] = {
new Data(1,100),
new Data(1,500),
new Data(1,200),
new Data(2,400),
new Data(2,200)
};
int AbstractTotal::size = sizeof(list) / sizeof(list[0]);
AbstractTotal::AbstractTotal(void) : total(0) {}
AbstractTotal::~AbstractTotal(void) {}
void AbstractTotal::operation(void)
{
AbstractSummary* sum = getSummary();
total = sum->calculateTotal();
delete sum;
}
SubTotal.h #include "AbstractTotal.h"
class SubTotal : public AbstractTotal
{
public:
SubTotal(void);
virtual ~SubTotal(void);
AbstractSummary* getSummary(void);
int getDivision(int);
int getTotal(int);
}; SubTotal.cpp #include "SubTotal.h"
#include "SubTotalSummary.h"
#include "SubDivisionName.h"
SubTotal::SubTotal(void) {}
SubTotal::~SubTotal(void) {}
AbstractSummary* SubTotal::getSummary(void) {
return new SubTotalSummary(list, size);
}
int SubTotal::getDivision(int n) {
return total[n]->no; // 区分
}
int SubTotal::getTotal(int n) {
return total[n]->value; // 合計値
}
WholeTotal.h #include "AbstractTotal.h"
class WholeTotal : public AbstractTotal
{
public:
WholeTotal(void);
virtual ~WholeTotal(void);
AbstractSummary* getSummary();
int getDivision(int);
int getTotal(int);
}; WholeTotal.cpp #include "WholeTotal.h"
#include "WholeTotalSummary.h"
#include "WholeDivisionName.h"
WholeTotal::WholeTotal(void) {}
WholeTotal::~WholeTotal(void) {}
AbstractSummary* WholeTotal::getSummary(void) {
return new WholeTotalSummary(list, size);
}
int WholeTotal::getDivision(int n) {
return total[0]->no; // 区分
}
int WholeTotal::getTotal(int n) {
return total[0]->value; // 合計値
}
AbstractFactory.h #include "AbstractTotal.h"
#include "AbstractDivisionName.h"
class AbstractFactory
{
public:
virtual AbstractTotal* getTotal(void) = 0;
virtual AbstractDivisionName* getDivisionName(void) = 0;
}; AbstractFactory.cpp #include "AbstractFactory.h"
SubFactory.h #include "AbstractFactory.h"
class SubFactory : public AbstractFactory
{
public:
SubFactory(void);
virtual ~SubFactory(void);
AbstractTotal* getTotal(void);
AbstractDivisionName* getDivisionName(void);
}; SubFactory.cpp #include "SubFactory.h"
#include "SubTotal.h"
#include "SubDivisionName.h"
SubFactory::SubFactory(void) {}
SubFactory::~SubFactory(void) {}
AbstractTotal* SubFactory::getTotal(void)
{
return new SubTotal();
}
AbstractDivisionName* SubFactory::getDivisionName(void)
{
return new SubDivisionName();
}
WholeFactory.h #include "AbstractFactory.h"
class WholeFactory : public AbstractFactory
{
public:
WholeFactory(void);
virtual ~WholeFactory(void);
AbstractTotal* getTotal(void);
AbstractDivisionName* getDivisionName(void);
}; WholeFactory.cpp #include "WholeFactory.h"
#include "WholeTotal.h"
#include "WholeDivisionName.h"
WholeFactory::WholeFactory(void) {}
WholeFactory::~WholeFactory(void) {}
AbstractTotal* WholeFactory::getTotal(void)
{
return new WholeTotal();
}
AbstractDivisionName* WholeFactory::getDivisionName(void)
{
return new WholeDivisionName();
}
Factory.h #include "AbstractFactory.h"
class Factory
{
private:
AbstractFactory* factory;
public:
Factory(void);
Factory(char*);
virtual ~Factory(void);
AbstractFactory* getFactory(void);
}; Factory.cpp #include "Factory.h"
#include "SubFactory.h"
#include "WholeFactory.h"
using namespace std;
Factory::Factory(void) : factory() {}
Factory::Factory(char* c)
{
if (strcmp("sub", c) == 0) {
factory = new SubFactory();
}
else {
factory = new WholeFactory();
}
}
Factory::~Factory() {}
AbstractFactory* Factory::getFactory(void)
{
return factory;
}
main.cpp #include <iostream>
using namespace std;
#include "Factory.h"
#include "Subtotal.h"
#include "WholeTotal.h"
#include "AbstractDivisionName.h"
int main(int argc, char* argv[])
{
AbstractFactory* factory = (new Factory(argv[1]))->getFactory();
AbstractTotal* total = factory->getTotal();
total->operation();
AbstractDivisionName* divisionName = factory->getDivisionName();
cout << divisionName->getName(total->getDivision(0)) << " " << total->getTotal(0) << endl;
delete divisionName;
delete total;
delete factory;
return 0;
}
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.cs abstract class AbstractTotal
{
// 区分, 数値 (実際にはDBなどから数値を得る。)
protected Data[] list = new Data[] {
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
};
protected Data[] total;
public abstract AbstractSummary GetSummary();
public abstract int GetDivision(int n);
public abstract int GetTotal(int n);
public abstract AbstractDivisionName CreateDivisionName();
public void Operation()
{
AbstractSummary sum = GetSummary();
total = sum.CalculateTotal();
}
}
SubTotal.cs class SubTotal : AbstractTotal
{
public override AbstractSummary GetSummary()
{
return new SubTotalSummary(list);
}
public override int GetDivision(int n)
{
return total[n].no; // 区分
}
public override int GetTotal(int n)
{
return total[n].value; // 合計値
}
public override AbstractDivisionName CreateDivisionName()
{
return new SubDivisionName();
}
}
WholeTotal.cs class WholeTotal : AbstractTotal
{
public override AbstractSummary GetSummary()
{
return new WholeTotalSummary(list);
}
public override int GetDivision(int n)
{
return total[0].no;
}
public override int GetTotal(int n)
{
return total[0].value;
}
public override AbstractDivisionName CreateDivisionName()
{
return new WholeDivisionName();
}
}
Program.cs class Program
{
static void Main(string[] args)
{
AbstractTotal total;
if (args[0] == "sub")
total = new SubTotal();
else
total = new WholeTotal();
total.Operation();
AbstractDivisionName divisionName = total.CreateDivisionName();
Console.WriteLine(divisionName.GetName(total.GetDivision(0)) + " " + total.GetTotal(0));
}
}
|
Abstract Factoryパターンを使用した例 AbstractTotal.cs abstract class AbstractTotal
{
// 区分, 数値 (実際にはDBなどから数値を得る。)
protected Data[] list = new Data[] {
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
};
protected Data[] total;
public abstract AbstractSummary GetSummary();
public abstract int GetDivision(int n);
public abstract int GetTotal(int n);
public void Operation()
{
AbstractSummary sum = GetSummary();
total = sum.CalculateTotal();
}
}
SubTotal.cs class SubTotal : AbstractTotal
{
public override AbstractSummary GetSummary()
{
return new SubTotalSummary(list);
}
public override int GetDivision(int n)
{
return total[n].no; // 区分
}
public override int GetTotal(int n)
{
return total[n].value; // 合計値
}
}
WholeTotal.cs class WholeTotal : AbstractTotal
{
public override AbstractSummary GetSummary()
{
return new WholeTotalSummary(list);
}
public override int GetDivision(int n)
{
return total[0].no;
}
public override int GetTotal(int n)
{
return total[0].value;
}
}
AbstractFactory.cs abstract class AbstractFactory
{
public abstract AbstractTotal GetTotal();
public abstract AbstractDivisionName GetDivisionName();
}
SubFactory.cs class SubFactory : AbstractFactory
{
public override AbstractTotal GetTotal()
{
return new SubTotal();
}
public override AbstractDivisionName GetDivisionName()
{
return new SubDivisionName();
}
}
WholeFactory.cs class WholeFactory : AbstractFactory
{
public override AbstractTotal GetTotal()
{
return new WholeTotal();
}
public override AbstractDivisionName GetDivisionName()
{
return new WholeDivisionName();
}
}
Factory.cs class Factory
{
private AbstractFactory factory;
public Factory(string c)
{
if (c == "sub")
{
factory = new SubFactory();
}
else
{
factory = new WholeFactory();
}
}
public AbstractFactory GetFactory()
{
return factory;
}
}
Program.cs class Program
{
static void Main(string[] args)
{
AbstractFactory factory = new Factory(args[0]).GetFactory();
AbstractTotal total = factory.GetTotal();
total.Operation();
AbstractDivisionName divisionName = factory.GetDivisionName();
Console.WriteLine(divisionName.GetName(total.GetDivision(0)) + " " + total.GetTotal(0));
}
}
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
既存クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.vb Public MustInherit Class AbstractTotal
Protected list As Data() = {
New Data(1, 100),
New Data(1, 500),
New Data(1, 200),
New Data(2, 400),
New Data(2, 200)
}
Protected total As Data()
Public MustOverride Function GetSummary() As AbstractSummary
Public MustOverride Function GetDivision(n As Integer) As Integer
Public MustOverride Function GetTotal(n As Integer) As Integer
Public MustOverride Function CreateDivisionName() As AbstractDivisionName
Public Sub Operation()
Dim sum As AbstractSummary = GetSummary()
total = sum.CalculateTotal()
End Sub
End Class
SubTotal.vb Public Class SubTotal
Inherits AbstractTotal
Public Overrides Function GetSummary() As AbstractSummary
Return New SubTotalSummary(list)
End Function
Public Overrides Function GetDivision(n As Integer) As Integer
Return total(n).no ' 区分
End Function
Public Overrides Function GetTotal(n As Integer) As Integer
Return total(n).value ' 合計値
End Function
Public Overrides Function CreateDivisionName() As AbstractDivisionName
Return New SubDivisionName()
End Function
End Class
WholeTotal.vb Public Class WholeTotal
Inherits AbstractTotal
Public Overrides Function GetSummary() As AbstractSummary
Return New SubTotalSummary(list)
End Function
Public Overrides Function GetDivision(n As Integer) As Integer
Return total(0).no ' 区分
End Function
Public Overrides Function GetTotal(n As Integer) As Integer
Return total(0).value ' 合計値
End Function
Public Overrides Function CreateDivisionName() As AbstractDivisionName
Return New WholeDivisionName()
End Function
End Class
Program.vb Module Main
Sub Main(ByVal args() As String)
Dim total As AbstractTotal
If args(0) = "sub" Then
total = New SubTotal()
Else
total = New WholeTotal()
End If
total.Operation()
Dim divisionName As AbstractDivisionName = total.CreateDivisionName()
Console.WriteLine(divisionName.GetName(total.GetDivision(0)) & " " & total.GetTotal(0))
End Sub
End Module
|
Abstract Factoryパターンを使用した例 AbstractTotal.vb Public MustInherit Class AbstractTotal
Protected list As Data() = {
New Data(1, 100),
New Data(1, 500),
New Data(1, 200),
New Data(2, 400),
New Data(2, 200)
}
Protected total As Data()
Public MustOverride Function GetSummary() As AbstractSummary
Public MustOverride Function GetDivision(n As Integer) As Integer
Public MustOverride Function GetTotal(n As Integer) As Integer
Public Sub Operation()
Dim sum As AbstractSummary = GetSummary()
total = sum.CalculateTotal()
End Sub
End Class
SubTotal.vb Public Class SubTotal
Inherits AbstractTotal
Public Overrides Function GetSummary() As AbstractSummary
Return New SubTotalSummary(list)
End Function
Public Overrides Function GetDivision(n As Integer) As Integer
Return total(n).no ' 区分
End Function
Public Overrides Function GetTotal(n As Integer) As Integer
Return total(n).value ' 合計値
End Function
End Class
WholeTotal.vb Public Class WholeTotal
Inherits AbstractTotal
Public Overrides Function GetSummary() As AbstractSummary
Return New SubTotalSummary(list)
End Function
Public Overrides Function GetDivision(n As Integer) As Integer
Return total(0).no ' 区分
End Function
Public Overrides Function GetTotal(n As Integer) As Integer
Return total(0).value ' 合計値
End Function
End Class
Factory.vb Public Class Factory
Private factory As AbstractFactory
Public Sub New(c As String) As AbstractTotal
If c = "sub" Then
factory = New SubFactory()
Else
factory = New WholeFactory()
End If
End Sub
Public Function GetFactory() As AbstractFactory
Return factory
End Function
End Class
Program.vb Module Main(ByVal args() As String)
Sub Main(ByVal args() As String)
Dim factory As AbstractFactory = New Factory(args(0)).GetFactory()
Dim total As AbstractTotal = factory.GetTotal()
total.Operation()
Dim divisionName As AbstractDivisionName = factory.GetDivisionName()
Console.WriteLine(divisionName.GetName(total.GetDivision(0)) & " " & total.GetTotal(0))
End Sub
End Module
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(Main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.js module.exports = class AbstractTotal {
constructor() {
// 区分 , 数値 (実際には DB などから数値を得る。)
this.list = Array.of(
{ no:1, value:100 }, { no:1, value:500 }, { no:1, value:200 },
{ no:2, value:400 }, { no:2, value:200 }
);
}
getDivision() { console.log("getDivision メソッドを定義してください。"); }
getTotal() { console.log("getTotal メソッドを定義してください。"); }
getSummary() { console.log("getSummary メソッドを定義してください。"); }
createDivisionName() { console.log("createDivisionName メソッドを定義してください。"); }
operation() {
let sum = this.getSummary();
this.total = sum.calculateTotal(); // 合計値
}
}
SubTotal.js const AbstractTotal = require("./AbstractTotal.js");
const SubTotalSummary = require("./SubTotalSummary.js");
module.exports = class SubTotal extends AbstractTotal {
getSummary() {
return new SubTotalSummary(this.list);
}
getDivision(n) {
return this.total[n].no; // 区分
}
getTotal(n) {
return this.total[n].value; // 合計値
}
createDivisionName() {
return new SubDivisionName();
}
}
WholeTotal.js const AbstractTotal = require("./AbstractTotal.js");
const WholeTotalSummary = require("./WholeTotalSummary.js");
module.exports = class WholeTotal extends AbstractTotal {
getSummary() {
return new WholeTotalSummary(this.list);
}
getDivision(n) {
return this.total[0].no; // 区分
}
getTotal(n) {
return this.total[0].value; // 合計値
}
createDivisionName() {
return new WholeDivisionName();
}
}
Main.js const SubTotal = require("./SubTotal.js");
const WholeTotal = require("./WholeTotal.js");
let total = null;
if (process.argv[2] == "sub")
total = new SubTotal();
else
total = new WholeTotal();
total.operation(); // 区分ごとの合計値算
let divisionName = total.createDivisionName();
process.stdout.write(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0) + "\n");
|
Abstract Factoryパターンを使用した例 AbstractTotal.js module.exports = class AbstractTotal {
constructor() {
// 区分 , 数値 (実際には DB などから数値を得る。)
this.list = Array.of(
{ no:1, value:100 }, { no:1, value:500 }, { no:1, value:200 },
{ no:2, value:400 }, { no:2, value:200 }
);
}
getDivision() { console.log("getDivision メソッドを定義してください。"); }
getTotal() { console.log("getTotal メソッドを定義してください。"); }
getSummary() { console.log("getSummary メソッドを定義してください。"); }
operation() {
let sum = this.getSummary();
this.total = sum.calculateTotal(); // 合計値
}
}
SubTotal.js const AbstractTotal = require("./AbstractTotal.js");
const SubTotalSummary = require("./SubTotalSummary.js");
module.exports = class SubTotal extends AbstractTotal {
getSummary() {
return new SubTotalSummary(this.list);
}
getDivision(n) {
return this.total[n].no; // 区分
}
getTotal(n) {
return this.total[n].value; // 合計値
}
}
WholeTotal.js const AbstractTotal = require("./AbstractTotal.js");
const WholeTotalSummary = require("./WholeTotalSummary.js");
module.exports = class WholeTotal extends AbstractTotal {
getSummary() {
return new WholeTotalSummary(this.list);
}
getDivision(n) {
return this.total[0].no; // 区分
}
getTotal(n) {
return this.total[0].value; // 合計値
}
}
AbstractFactory.js module.exports = class AbstractFactory {
getTotal() { console.log("getTotal メソッドを定義してください。"); }
getDivisionName() { console.log("getDivisionName メソッドを定義してください。"); }
}
SubFactory.js const AbstractFactory = require("./AbstractFactory.js");
const SubTotal = require("./SubTotal.js");
const SubDivisionName = require("./SubDivisionName.js");
module.exports = class SubFactory extends AbstractFactory {
getTotal() {
return new SubTotal();
}
getDivisionName() {
return new SubDivisionName();
}
}
WholeFactory.js const AbstractFactory = require("./AbstractFactory.js");
const WholeTotal = require("./WholeTotal.js");
const WholeDivisionName = require("./WholeDivisionName.js");
module.exports = class WholeFactory {
getTotal() {
return new WholeTotal();
}
getDivisionName() {
return new WholeDivisionName();
}
}
Factory.js const SubTotal = require("./SubTotal.js");
const SubFactory = require("./SubFactory.js");
const WholeFactory = require("./WholeFactory.js");
module.exports = class Factory {
constructor(c) {
if (c == "sub") {
this.factory = new SubFactory();
}
else {
this.factory = new WholeFactory();
}
}
getFactory() {
return this.factory;
}
}
Main.js const Factory = require("./Factory.js");
let factory = new Factory(process.argv[2]).getFactory();
let total = factory.getTotal();
total.operation(); // 区分ごとの合計値算
let divisionName = factory.getDivisionName();
process.stdout.write(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0) + "\n");
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.pm package AbstractTotal {
sub new {
my ($class) = @_;
# 区分 , 数値 (実際には DB などから数値を得る。)
my $this = { list => [
{ no:1, value:100 }, { no:1, value:500 }, { no:1, value:200 },
{ no:2, value:400 }, { no:2, value:200 }
]};
return bless $this, $class;
}
sub getDivision { print "getDivision メソッドを定義してください。"; }
sub getTotal { print "getTotal メソッドを定義してください。"; }
sub getSummary { print "getSummary メソッドを定義してください。"; }
sub createDivisionName() { print "createDivisionName メソッドを定義してください。"; }
sub operation {
my ($this) = @_;
my $sum = $this->getSummary();
@{$this->{total}} = $sum->calculateTotal(); # 合計値
}
}
1;
SubTotal.pm use SubTotalSummary;
use SubDivisionName;
package SubTotal {
use base qw(AbstractTotal);
sub new {
my ($class) = @_;
my $this = $class->SUPER::new();
}
sub getSummary {
my ($this) = @_;
return new SubTotalSummary(\@{$this->{list}});
}
sub getDivision {
my ($this, $no) = @_;
return $this->{total}[$no]->{no}; # 区分
}
sub getTotal {
my ($this, $no) = @_;
return $this->{total}[$no]->{value}; # 合計値
}
sub createDivisionName() {
return new SubDivisionName();
}
}
1;
WholeTotal.pm use WholeTotalSummary;
use WholeDivisionName;
package WholeTotal {
use base qw(AbstractTotal);
sub new {
my ($class) = @_;
my $this = $class->SUPER::new();
}
sub getSummary {
my ($this) = @_;
return new WholeTotalSummary(\@{$this->{list}});
}
sub getDivision {
my ($this) = @_;
return $this->{total}[0]->{no}; # 区分
}
sub getTotal {
my ($this) = @_;
return $this->{total}[0]->{value}; # 合計値
}
sub createDivisionName() {
return new WholeDivisionName();
}
}
1;
Main.pl use lib qw(./);
use SubTotal;
use WholeTotal;
my $total = null;
if ($ARGV[0] eq "sub") {
$total = new SubTotal();
}
else {
$total = new WholeTotal();
}
$total->operation(); # 区分ごとの合計値算
print $total->getTotal(0) . "\n"; # 合計値
|
Abstract Factoryパターンを使用した例 AbstractTotal.pm package AbstractTotal {
sub new {
my ($class) = @_;
# 区分 , 数値 (実際には DB などから数値を得る。)
my $this = { list => [
{ no:1, value:100 }, { no:1, value:500 }, { no:1, value:200 },
{ no:2, value:400 }, { no:2, value:200 }
]};
return bless $this, $class;
}
sub getDivision { print "getDivision メソッドを定義してください。"; }
sub getTotal { print "getTotal メソッドを定義してください。"; }
sub getSummary { print "getSummary メソッドを定義してください。"; }
sub operation {
my ($this) = @_;
my $sum = $this->getSummary();
@{$this->{total}} = $sum->calculateTotal(); # 合計値
}
}
1;
SubTotal.pm package SubTotal {
use base qw(AbstractTotal);
use SubTotalSummary;
sub new {
my ($class) = @_;
my $this = $class->SUPER::new();
}
sub getSummary {
my ($this) = @_;
return new SubTotalSummary(\@{$this->{list}});
}
sub getDivision {
my ($this, $no) = @_;
return $this->{total}[$no]->{no}; # 区分
}
sub getTotal {
my ($this, $no) = @_;
return $this->{total}[$no]->{value}; # 合計値
}
}
1;
WholeTotal.pm use WholeTotalSummary;
package WholeTotal {
use base qw(AbstractTotal);
sub new {
my ($class) = @_;
my $this = $class->SUPER::new();
}
sub getSummary {
my ($this) = @_;
return new WholeTotalSummary(\@{$this->{list}});
}
sub getDivision {
my ($this) = @_;
return $this->{total}[0]->{no}; # 区分
}
sub getTotal {
my ($this) = @_;
return $this->{total}[0]->{value}; # 合計値
}
}
1;
AbstractFactory.pm package AbstractFactory {
sub new {
return bless {}, $_[0];
}
sub getTotal() { print "getTotal メソッドを定義してください。"; }
sub getDivisionName() { print "getDivisionName メソ\ッドを定義してください。"; }
}
1;
SubFactory.pm use SubTotal;
use SubDivisionName;
package SubFactory {
use base qw(AbstractFactory);
sub new {
return bless {}, $_[0];
}
sub getTotal() {
return new SubTotal();
}
sub getDivisionName() {
return new SubDivisionName();
}
}
1;
WholeFactory.pm use WholeTotal;
use WholeDivisionName;
package WholeFactory {
use base qw(AbstractFactory);
sub new {
return bless {}, $_[0];
}
sub getTotal() {
return new WholeTotal();
}
sub getDivisionName() {
return new WholeDivisionName();
}
}
1;
Factory.pm use SubFactory;
use WholeFactory;
package Factory {
sub new {
my ($class, $c) = @_;
if ($c eq "sub") {
$this = { factory => new SubFactory() };
}
else {
$this = { factory => new WholeFactory() };
}
return bless $this, $class;
}
sub getFactory() {
my ($this) = @_;
return $this->{factory};
}
}
1;
Main.pl use lib qw(./);
use Factory;
my $factory = new Factory($ARGV[0])->getFactory();
my $total = $factory->getTotal();
$total->operation();
my $divisionName = $factory->getDivisionName();
print $divisionName->getName($total->getDivision(0)) . " " . $total->getTotal(0) . "\n";
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な $factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.rb class AbstractTotal
def initialize()
# 区分 , 数値 (実際には DB などから数値を得る。)
@list = [
{ no:1, value:100 }, { no:1, value:500 }, { no:1, value:200 },
{ no:2, value:400 }, { no:2, value:200 }
]
end
def getDivision()
puts "getDivision メソッドを定義してください。"
end
def getTotal()
puts "getTotal メソッドを定義してください。"
end
def getSummary()
puts "getSummary メソッドを定義してください。"
end
def createDivisionName()
puts "createDivisionName メソッドを定義してください。"
end
def operation()
sum = getSummary()
@total = sum.calculateTotal() # 合計値
end
end
SubTotal.rb require './AbstractTotal.js'
require './SubTotalSummary'
class SubTotal < AbstractTotal
def initialize()
super()
end
def getSummary()
return SubTotalSummary.new(@list)
end
def getDivision(n)
return @total[n].fetch(:no) # 区分
end
def getTotal(n)
return this.@total[n].fetch(:value) # 合計値
end
def createDivisionName()
return SubDivisionName.new()
end
end
WholeTotal.rb require './AbstractTotal'
require './WholeTotalSummary'
class WholeTotal < AbstractTotal
def initialize()
super()
end
def getSummary()
return WholeTotalSummary.new(@list)
end
def getDivision(n)
return @total[0].fetch(:no) # 区分
end
def getTotal(n)
return @total[0].fetch(:value) # 合計値
end
def createDivisionName()
return WholeDivisionName.new()
end
end
Main.rb require './SubTotal'
require './WholeTotal'
if (ARGV[0] == "sub")
total = SubTotal.new()
else
total = WholeTotal.new()
end
total.operation() # 区分ごとの合計値算
divisionName = total.createDivisionName()
puts divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0).to_s
|
Abstract Factoryパターンを使用した例 AbstractTotal.rb class AbstractTotal
def initialize()
# 区分 , 数値 (実際には DB などから数値を得る。)
@list = [
{ no:1, value:100 }, { no:1, value:500 }, { no:1, value:200 },
{ no:2, value:400 }, { no:2, value:200 }
]
end
def getDivision()
puts "getDivision メソッドを定義してください。"
end
def getTotal()
puts "getTotal メソッドを定義してください。"
end
def getSummary()
puts "getSummary メソッドを定義してください。"
end
def operation()
sum = getSummary()
@total = sum.calculateTotal() # 合計値
end
end
SubTotal.rb require './AbstractTotal'
require './SubTotalSummary'
class SubTotal < AbstractTotal
def initialize()
super()
end
def getSummary()
return SubTotalSummary.new(@list)
end
def getDivision(n)
return @total[n].fetch(:no) # 区分
end
def getTotal(n)
return this.@total[n].fetch(:value) # 合計値
end
end
WholeTotal.rb require './AbstractTotal'
require './WholeTotalSummary'
class WholeTotal < AbstractTotal
def initialize()
super()
end
def getSummary()
return WholeTotalSummary.new(@list)
end
def getDivision(n)
return @total[0].fetch(:no) # 区分
end
def getTotal(n)
return @total[0].fetch(:value) # 合計値
end
end
AbstractFactory.rb class AbstractFactory
def getTotal()
puts "getTotal メソッドを定義してください。"
end
def getDivisionName()
puts "getDivisionName メソッドを定義してください。"
end
end
SubFactory.rb require './AbstractFactory'
require './SubTotal'
require './SubDivisionName'
class SubFactory < AbstractFactory
def getTotal()
return SubTotal.new();
end
def getDivisionName()
return SubDivisionName.new();
end
end
WholeFactory.rb require './AbstractFactory'
require './WholeTotal'
require './WholeDivisionName'
class WholeFactory < AbstractFactory
def getTotal()
return WholeTotal.new();
end
def getDivisionName()
return WholeDivisionName.new();
end
end
Factory.rb require './SubFactory'
require './WholeFactory'
class Factory
def initialize(c)
if (c == "sub")
@factory = SubFactory.new()
else
@factory = WholeFactory.new()
end
end
def getFactory()
return @factory
end
end
Main.rb require './Factory'
factory = Factory.new(ARGV[0]).getFactory()
total = factory.getTotal()
total.operation() # 区分ごとの合計値算
divisionName = factory.getDivisionName();
puts divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0).to_s
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.py from abc import ABCMeta, abstractmethod
class AbstractTotal(metaclass=ABCMeta):
def __init__(self):
# 区分 , 数値 (実際には DB などから数値を得る。)
self.list = [
{ "no":1, "value":100 }, { "no":1, "value":500 },
{ "no":1, "value":200 }, { "no":2, "value":400 },
{ "no":2, "value":200 }
]
@abstractmethod
def getDivision(self, n):
pass
@abstractmethod
def getTotal(self, n):
pass
@abstractmethod
def getSummary(self):
pass
@abstractmethod
def createDivisionName(self):
pass
def operation(self):
sum = self.getSummary()
self.total = sum.calculateTotal() # 合計値
SubTotal.py from AbstractTotal import AbstractTotal
from SubTotalSummary import SubTotalSummary
from SubDivisionName import SubDivisionName
class SubTotal(AbstractTotal):
def getSummary(self):
return SubTotalSummary(self.list)
def getDivision(self, n):
return self.total[n]["no"] # 区分
def getTotal(self, n):
return self.total[n]["value"] # 合計値
def createDivisionName(self):
return SubDivisionName()
WholeTotal.py from AbstractTotal import AbstractTotal
from WholeTotalSummary import WholeTotalSummary
from WholeDivisionName import WholeDivisionName
class WholeTotal(AbstractTotal):
def getSummary(self):
return WholeTotalSummary(self.list)
def getDivision(self, n):
return self.total[0]["no"] # 区分
def getTotal(self, n):
return self.total[0]["value"] # 合計値
def createDivisionName(self):
return WholeDivisionName()
Main.js import sys
from SubTotal import SubTotal
from WholeTotal import WholeTotal
if sys.argv[1] == "sub":
total = SubTotal()
else:
total = WholeTotal()
total.operation() # 区分ごとの合計値算
divisionName = total.createDivisionName()
print(divisionName.getName(total.getDivision(0)) + " " + str(total.getTotal(0)))
|
Abstract Factoryパターンを使用した例 AbstractTotal.py from abc import ABCMeta, abstractmethod
class AbstractTotal(metaclass=ABCMeta):
def __init__(self):
# 区分 , 数値 (実際には DB などから数値を得る。)
self.list = [
{ "no":1, "value":100 }, { "no":1, "value":500 },
{ "no":1, "value":200 }, { "no":2, "value":400 },
{ "no":2, "value":200 }
]
@abstractmethod
def getDivision(self, n):
pass
@abstractmethod
def getTotal(self, n):
pass
@abstractmethod
def getSummary(self):
pass
def operation(self):
sum = self.getSummary()
self.total = sum.calculateTotal() # 合計値
SubTotal.py from AbstractTotal import AbstractTotal
from SubTotalSummary import SubTotalSummary
class SubTotal(AbstractTotal):
def getSummary(self):
return SubTotalSummary(self.list)
def getDivision(self, n):
return self.total[n]["no"] # 区分
def getTotal(self, n):
return self.total[n]["value"] # 合計値
WholeTotal.py from AbstractTotal import AbstractTotal
from WholeTotalSummary import WholeTotalSummary
class WholeTotal(AbstractTotal):
def getSummary(self):
return WholeTotalSummary(self.list)
def getDivision(self, n):
return self.total[0]["no"] # 区分
def getTotal(self, n):
return self.total[0]["value"] # 合計値
AbstractFactory.py from abc import ABCMeta, abstractmethod
class AbstractFactory(metaclass=ABCMeta):
@abstractmethod
def getTotal(self):
pass
@abstractmethod
def getDivisionName(self):
pass
SubFactory.py from AbstractFactory import AbstractFactory
from SubTotal import SubTotal
from SubDivisionName import SubDivisionName
class SubFactory(AbstractFactory):
def getTotal(self):
return SubTotal()
def getDivisionName(self):
return SubDivisionName()
WholeFactory.py from AbstractFactory import AbstractFactory
from WholeTotal import WholeTotal
from WholeDivisionName import WholeDivisionName
class WholeFactory(AbstractFactory):
def getTotal(self):
return WholeTotal()
def getDivisionName(self):
return WholeDivisionName()
Factory.py from SubFactory import SubFactory
from WholeFactory import WholeFactory
class Factory:
def __init__(self, c):
if c == "sub":
self.factory = SubFactory()
else:
self.factory = WholeFactory()
def getFactory(self):
return self.factory
Main.js import sys
from Factory import Factory
factory = Factory(sys.argv[1]).getFactory()
total = factory.getTotal()
total.operation() # 区分ごとの合計値算
divisionName = factory.getDivisionName()
print(divisionName.getName(total.getDivision(0)) + " " + str(total.getTotal(0)))
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
既存クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.php <?php
require_once('Data.php');
abstract class AbstractTotal {
public function __construct() {
$this->list = array(
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
);
}
public abstract function getDivision($n);
public abstract function getTotal($n);
public abstract function getSummary();
public abstract function createDivisionName();
public function operation() {
$sum = $this->getSummary();
$this->total = $sum->calculateTotal();
}
}
?>
SubTotal.php <?php
require_once('AbstractTotal.php');
require_once('SubTotalSummary.php');
class SubTotal extends AbstractTotal {
public function __construct() {
parent::__construct();
}
public function getSummary() {
return new SubTotalSummary($this->list);
}
public function getDivision($n) {
return $this->total[$n]->no; // 区分
}
public function getTotal($n) {
return $this->total[$n]->value; // 合計値
}
public function createDivisionName() {
return new SubDivisionName();
}
}
?>
WholeTotal.php <?php
require_once('AbstractTotal.php');
require_once('WholeTotalSummary.php');
class SubTotal extends AbstractTotal {
public function __construct() {
parent::__construct();
}
public function getSummary() {
return new WholeTotalSummary($this->list);
}
public function getDivision($n) {
return $this->total[0]->no; // 区分
}
public function getTotal($n) {
return $this->total[0]->value; // 合計値
}
public function createDivisionName() {
return new WholeDivisionName();
}
}
?>
Main.php <?php
require_once('SubTotal.php');
require_once('WholeTotal.php');
if ($argv[1] == "sub")
$total = new SubTotal();
else
$total = new WholeTotal();
$total->operation(); // 区分ごとの合計値算
$divisionName = $total->createDivisionName();
print $divisionName->getName($total->getDivision(0)) . " " . $total->getTotal(0) . "\n";
?>
|
Abstract Factoryパターンを使用した例 AbstractTotal.php <?php
require_once('Data.php');
abstract class AbstractTotal {
public function __construct() {
$this->list = array(
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
);
}
public abstract function getDivision($n);
public abstract function getTotal($n);
public abstract function getSummary();
public function operation() {
$sum = $this->getSummary();
$this->total = $sum->calculateTotal();
}
}
?>
SubTotal.php <?php
require_once('AbstractTotal.php');
require_once('SubTotalSummary.php');
class SubTotal extends AbstractTotal {
public function __construct() {
parent::__construct();
}
public function getSummary() {
return new SubTotalSummary($this->list);
}
public function getDivision($n) {
return $this->total[$n]->no; // 区分
}
public function getTotal($n) {
return $this->total[$n]->value; // 合計値
}
}
?>
WholeTotal.php <?php
require_once('AbstractTotal.php');
require_once('WholeTotalSummary.php');
class SubTotal extends AbstractTotal {
public function __construct() {
parent::__construct();
}
public function getSummary() {
return new WholeTotalSummary($this->list);
}
public function getDivision($n) {
return $this->total[0]->no; // 区分
}
public function getTotal($n) {
return $this->total[0]->value; // 合計値
}
}
?>
AbstractFactory.php <?php
abstract class AbstractFactory {
public abstract function getTotal();
public abstract function getDivisionName();
}
?>
SubFactory.php <?php
require_once('AbstractFactory.php');
require_once('SubTotal.php');
require_once('SubDivisionName.php');
class SubFactory extends AbstractFactory {
public function getTotal() {
return new SubTotal();
}
public function getDivisionName() {
return new SubDivisionName();
}
}
?>
WholeFactory.php <?php
require_once('AbstractFactory.php');
require_once('WholeTotal.php');
require_once('WholeDivisionName.php');
class WholeFactory extends AbstractFactory {
public function getTotal() {
return new WholeTotal();
}
public function getDivisionName() {
return new WholeDivisionName();
}
}
?>
Factory.php <?php
require_once('SubFactory.php');
require_once('WholeFactory.php');
class Factory {
public function __construct($c) {
if ($c == "sub")
$this->factory = new SubFactory();
}
else {
$this->factory = new WholeFactory();
}
}
public function getFactory() {
return $this->factory;
}
}
?>
Main.php <?php
require_once('Factory.php');
$factory = (new Factory($argv[1]))->getFactory();
$total = $factory->getTotal();
$total->operation(); // 区分ごとの合計値算
$divisionName = $factory->getDivisionName();
print $divisionName->getName($total->getDivision(0)) . " " . $total->getTotal(0) . "\n";
?>
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な $factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.ts import {Data} from "./Data";
import {AbstractDivisionName} from "./AbstractDivisionName";
import {AbstractSummary} from "./AbstractSummary";
export
abstract class AbstractTotal {
protected list:Array<Data>;
protected total:Array<Data>;
public constructor() {
this.list = Array.of(
// 区分 , 数値 (実際には DB などから数値を得る。)
new Data(1, 100), new Data(1, 500), new Data(1, 200),
new Data(2, 400), new Data(2, 200)
);
}
public abstract getDivision(n:number):number;
public abstract getTotal(n:number):number;
public abstract getSummary():AbstractSummary;
public abstract createDivisionName():AbstractDivisionName;
public operation():void {
let sum:AbstractSummary = this.getSummary();
this.total = sum.calculateTotal();
}
}
SubTotal.ts import {AbstractTotal} from "./AbstractTotal";
import {AbstractSummary} from "./AbstractSummary";
import {AbstractDivisionName} from "./AbstractDivisionName";
import {SubTotalSummary} from "./SubTotalSummary";
import {SubDivisionName} from "./SubDivisionName";
export
class SubTotal extends AbstractTotal {
public getSummary():AbstractSummary {
return new SubTotalSummary(this.list);
}
public getDivision(n:number):number {
return this.total[n].no; // 区分
}
public getTotal(n:number):number {
return this.total[n].value; // 合計値
}
public createDivisionName():AbstractDivisionName {
return new SubDivisionName();
}
}
WholeTotal.ts import {AbstractTotal} from "./AbstractTotal";
import {AbstractSummary} from "./AbstractSummary";
import {AbstractDivisionName} from "./AbstractDivisionName";
import {WholeTotalSummary} from "./WholeTotalSummary";
import {WholeDivisionName} from "./WholeDivisionName";
export
class WholeTotal extends AbstractTotal {
public getSummary():WholeTotalSummary {
return new WholeTotalSummary(this.list);
}
public getDivision(n:number):number {
return total[0].no; // 区分
}
public getTotal(n:number):number {
return total[0].value; // 合計値
}
public createDivisionName():AbstractDivisionName {
return new WholeDivisionName();
}
}
Main.ts import {AbstractTotal} from "./AbstractTotal";
import {SubTotal} from "./SubTotal";
import {WholeTotal} from "./WholeTotal";
import {AbstractDivisionName} from "./AbstractDivisionName";
let total:AbstractTotal = null;
if (process.argv[2] == "sub")
total = new SubTotal();
else
total = new WholeTotal();
total.operation();
let divisionName:AbstractDivisionName = total.createDivisionName();
process.stdout.write(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0) + "\n");
|
Abstract Factoryパターンを使用した例 AbstractTotal.ts import {Data} from "./Data";
import {AbstractSummary} from "./AbstractSummary";
export
abstract class AbstractTotal {
protected list:Array<Data>;
protected total:Array<Data>;
public constructor() {
this.list = Array.of(
// 区分 , 数値 (実際には DB などから数値を得る。)
new Data(1, 100), new Data(1, 500), new Data(1, 200),
new Data(2, 400), new Data(2, 200)
);
}
public abstract getDivision(n:number):number;
public abstract getTotal(n:number):number;
public abstract getSummary():AbstractSummary;
public operation():void {
let sum:AbstractSummary = this.getSummary();
this.total = sum.calculateTotal();
}
}
SubTotal.ts import {AbstractTotal} from "./AbstractTotal";
import {AbstractSummary} from "./AbstractSummary";
import {SubTotalSummary} from "./SubTotalSummary";
export
class SubTotal extends AbstractTotal {
public getSummary():AbstractSummary {
return new SubTotalSummary(this.list);
}
public getDivision(n:number):number {
return total[n].no; // 区分
}
public getTotal(n:number):number {
return total[n].value; // 合計値
}
}
WholeTotal.ts import {AbstractTotal} from "./AbstractTotal";
import {AbstractSummary} from "./AbstractSummary";
import {WholeTotalSummary} from "./WholeTotalSummary";
export
class WholeTotal extends AbstractTotal {
public getSummary():WholeTotalSummary {
return new WholeTotalSummary(this.list);
}
public getDivision(n:number):number {
return this.total[0].no; // 区分
}
public getTotal(n:number):number {
return this.total[0].value; // 合計値
}
}
AbstractFactory.ts import {AbstractTotal} from "./AbstractTotal";
import {AbstractDivisionName} from "./AbstractDivisionName";
export
abstract class AbstractFactory {
public abstract getTotal():AbstractTotal;
public abstract getDivisionName():AbstractDivisionName;
}
SubFactory.ts import {AbstractFactory} from "./AbstractFactory";
import {AbstractTotal} from "./AbstractTotal";
import {SubTotal} from "./SubTotal";
import {AbstractDivisionName} from "./AbstractDivisionName";
import {SubDivisionName} from "./SubDivisionName";
export
class SubFactory extends AbstractFactory {
public getTotal():AbstractTotal {
return new SubTotal();
}
public getDivisionName():AbstractDivisionName {
return new SubDivisionName();
}
}
WholeFactory.ts import {AbstractFactory} from "./AbstractFactory";
import {AbstractTotal} from "./AbstractTotal";
import {WholeTotal} from "./WholeTotal";
import {AbstractDivisionName} from "./AbstractDivisionName";
import {WholeDivisionName} from "./WholeDivisionName";
export
class WholeFactory extends AbstractFactory {
public getTotal():AbstractTotal {
return new WholeTotal();
}
public getDivisionName():AbstractDivisionName {
return new WholeDivisionName();
}
}
Factory.ts import {AbstractFactory} from "./AbstractFactory";
import {SubFactory} from "./SubFactory";
import {WholeFactory} from "./WholeFactory";
export
class Factory {
private factory:AbstractFactory;
public constructor(c:string) {
if ("sub" == c) {
this.factory = new SubFactory();
}
else {
this.factory = new WholeFactory();
}
}
public getFactory():AbstractFactory {
return this.factory;
}
}
Main.ts import {AbstractDivisionName} from "./AbstractDivisionName";
import { AbstractFactory } from "./AbstractFactory";
import { AbstractTotal } from "./AbstractTotal";
let factory:AbstractFactory = new Factory(process.argv[2]).getFactory();
let total:AbstractTotal = factory.getTotal();
total.operation();
let divisionName:AbstractDivisionName = factory.getDivisionName();
process.stdout.write(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0) + "\n");
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.swift public class AbstractTotal {
internal var list:[Data] = [
// 区分 , 数値 (実際には DB などから数値を得る。)
Data(1, 100), Data(1, 500), Data(1, 200),
Data(2, 400), Data(2, 200)
]
internal var total:[Data] = []
public func getDivision(_ n:Int) -> Int {
fatalError("getDivision メソッドを定義してください。")
}
public func getTotal(_ n:Int) -> Int {
fatalError("getTotal メソッドを定義してください。")
}
public func getSummary() -> AbstractSummary {
fatalError("getSummary メソッドを定義してください。")
}
public func createDivisionName() -> AbstractDivisionName {
fatalError("createDivisionName メソッドを定義してください。")
}
public func operation() {
let sum:AbstractSummary = getSummary()
total = sum.calculateTotal()
}
}
SubTotal.swift public class SubTotal : AbstractTotal {
public override func getSummary() -> AbstractSummary {
return SubTotalSummary(list)
}
public override func getDivision(_ n:Int) -> Int {
return total[n].no // 区分
}
public override func getTotal(_ n:Int) -> Int {
return total[n].value // 合計値
}
public override func createDivisionName() -> AbstractDivisionName {
return SubDivisionName()
}
}
WholeTotal.swift public class WholeTotal : AbstractTotal {
public override func getSummary() -> WholeTotalSummary {
return WholeTotalSummary(list)
}
public override func getDivision(_ n:Int) -> Int {
return total[0].no // 区分
}
public override func getTotal(_ n:Int) -> Int {
return total[0].value // 合計値
}
public override func createDivisionName() -> AbstractDivisionName {
return WholeDivisionName()
}
}
Main.swift var total:AbstractTotal
if CommandLine.arguments[1] == "sub" {
total = SubTotal()
}
else {
total = WholeTotal()
}
total.operation()
let divisionName:AbstractDivisionName = total.createDivisionName()
print(divisionName.getName(total.getDivision(0)) + " " + String(total.getTotal(0)) + "\n")
|
Abstract Factoryパターンを使用した例 AbstractTotal.swift public class AbstractTotal {
internal var list:[Data] = [
// 区分 , 数値 (実際には DB などから数値を得る。)
Data(1, 100), Data(1, 500), Data(1, 200),
Data(2, 400), Data(2, 200)
]
internal var total:[Data] = []
public func getDivision(_ n:Int) -> Int {
fatalError("getDivision メソッドを定義してください。")
}
public func getTotal(_ n:Int) -> Int {
fatalError("getTotal メソッドを定義してください。")
}
public func getSummary() -> AbstractSummary {
fatalError("getSummary メソッドを定義してください。")
}
public func operation() {
let sum:AbstractSummary = getSummary()
total = sum.calculateTotal()
}
}
SubTotal.swift public class SubTotal : AbstractTotal {
public override func getSummary() -> AbstractSummary {
return SubTotalSummary(list)
}
public override func getDivision(_ n:Int) -> Int {
return total[n].no // 区分
}
public override func getTotal(_ n:Int) -> Int {
return total[n].value // 合計値
}
}
WholeTotal.swift public class WholeTotal : AbstractTotal {
public override func getSummary() -> AbstractSummary {
return WholeTotalSummary(list)
}
public override func getDivision(_ n:Int) -> Int {
return total[0].no; // 区分
}
public override func getTotal(_ n:Int) -> Int {
return total[0].value // 合計値
}
}
AbstractFactory.swift public class AbstractFactory {
public func getTotal() -> AbstractTotal {
fatalError("getTotal メソッドを定義してください。")
}
public func getDivisionName() -> AbstractDivisionName {
fatalError("getDivisionName メソッドを定義してください。")
}
}
SubFactory.swift public class SubFactory : AbstractFactory {
public override func getTotal() -> AbstractTotal {
return SubTotal()
}
public override func getDivisionName() -> AbstractDivisionName {
return SubDivisionName()
}
}
WholeFactory.swift public class WholeFactory : AbstractFactory {
public override func getTotal() -> AbstractTotal {
return WholeTotal()
}
public override func getDivisionName() -> AbstractDivisionName {
return WholeDivisionName()
}
}
Factory.swift public class Factory {
private var factory:AbstractFactory
public init(_ c:String) {
if "sub" == c {
factory = SubFactory()
}
else {
factory = WholeFactory()
}
}
public func getFactory() -> AbstractFactory {
return factory
}
}
Main.swift let factory:AbstractFactory = Factory(CommandLine.arguments[1]).getFactory()
let total:AbstractTotal = factory.getTotal()
total.operation()
let divisionName:AbstractDivisionName = factory.getDivisionName()
print(divisionName.getName(total.getDivision(0)) + " " + String(total.getTotal(0)) + "\n")
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.kt abstract class AbstractTotal {
// 区分 , 数値 (実際には DB などから数値を得る。)
protected var list =
Data(1, 100), Data(1, 500), Data(1, 200),
Data(2, 400), Data(2, 200)
)
internal lateinit var total: Array<Data?>
abstract fun getDivision(n: Int): Int
abstract fun getTotal(n: Int): Int
abstract fun getSummary(): AbstractSummary
abstract fun createDivisionName(): AbstractDivisionName
internal fun operation() {
val sum: AbstractSummary = getSummary()
this.total = sum.calculateTotal()
}
}
SubTotal.kt class SubTotal : AbstractTotal() {
override fun getSummary(): AbstractSummary {
return SubTotalSummary(list)
}
override fun getDivision(n: Int): Int {
return total[n]!!.no // 区分
}
override fun getTotal(n: Int): Int {
return total[n]!!.value // 合計値
}
override fun createDivisionName(): AbstractDivisionName {
return SubDivisionName()
}
}
WholeTotal.kt class WholeTotal : AbstractTotal() {
override fun getSummary(): WholeTotalSummary {
return WholeTotalSummary(list)
}
override fun getDivision(n: Int): Int {
return total[0]!!.no // 区分
}
override fun getTotal(n: Int): Int {
return total[0]!!.value // 合計値
}
override fun createDivisionName(): AbstractDivisionName {
return WholeDivisionName()
}
}
Main.kt fun main(args: Array<String>) {
val total: AbstractTotal = if (args[0] == "sub") {
SubTotal()
}
else {
WholeTotal()
}
total.operation()
val divisionName: AbstractDivisionName = total.createDivisionName()
println(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0))
}
|
Abstract Factoryパターンを使用した例 AbstractTotal.kt abstract class AbstractTotal {
protected var list = arrayOf(
// 区分 , 数値 (実際には DB などから数値を得る。)
Data(1, 100), Data(1, 500), Data(1, 200),
Data(2, 400), Data(2, 200)
)
internal lateinit var total: Array<Data?> // 合計値
abstract fun getDivision(n: Int): Int
abstract fun getTotal(n: Int): Int
abstract fun getSummary(): AbstractSummary
internal fun operation() {
val sum: AbstractSummary = getSummary()
this.total = sum.calculateTotal()
}
}
SubTotal.kt class SubTotal : AbstractTotal() {
override fun getSummary(): AbstractSummary {
return SubTotalSummary(list)
}
override fun getDivision(n: Int): Int {
return total[n]!!.no // 区分
}
override fun getTotal(n: Int): Int {
return total[n]!!.value // 合計値
}
}
WholeTotal.kt class WholeTotal : AbstractTotal() {
override fun getSummary(): AbstractSummary {
return WholeTotalSummary(list)
}
override fun getDivision(n: Int): Int {
return total[0]!!.no // 区分
}
override fun getTotal(n: Int): Int {
return total[0]!!.value // 合計値
}
}
AbstractFactory.kt abstract class AbstractFactory {
abstract fun getTotal(): AbstractTotal
abstract fun getDivisionName(): AbstractDivisionName
}
SubFactory.kt class SubFactory : AbstractFactory() {
override fun getTotal(): AbstractTotal {
return SubTotal()
}
override fun getDivisionName(): AbstractDivisionName {
return SubDivisionName()
}
}
WholeFactory.kt class WholeFactory : AbstractFactory() {
override fun getTotal(): AbstractTotal {
return WholeTotal()
}
override fun getDivisionName(): AbstractDivisionName {
return WholeDivisionName()
}
}
Factory.kt class Factory(private val c: String) {
private var factory: AbstractFactory
init {
factory = if ("sub" == c) {
SubFactory()
}
else {
WholeFactory()
}
}
fun getFactory(): AbstractFactory {
return factory
}
}
Main.kt fun main(args: Array<String>) {
var factory = Factory(args[0]).getFactory()
val total = factory.getTotal()
total.operation()
val divisionName = factory.getDivisionName()
println(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0))
}
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.scala abstract class AbstractTotal {
// 区分 , 数値 (実際には DB などから数値を得る。)
protected var list = Seq(
new Data(1, 100), new Data(1, 500), new Data(1, 200),
new Data(2, 400), new Data(2, 200)
)
protected var total: Array[Data] = null
def getDivision(n: Int): Int
def getTotal(n: Int): Int
def getSummary(): AbstractSummary
def createDivisionName(): AbstractDivisionName
def operation() {
val sum: AbstractSummary = getSummary()
total = sum.calculateTotal()
}
}
SubTotal.scala class SubTotal extends AbstractTotal() {
def getSummary(): AbstractSummary = new SubTotalSummary(list)
def getDivision(n: Int): Int = total(n).no // 区分
def getTotal(n: Int): Int = total(n).value // 合計値
def createDivisionName(): AbstractDivisionName = new SubDivisionName()
}
WholeTotal.scala class WholeTotal extends AbstractTotal() {
def getSummary(): AbstractSummary = new WholeTotalSummary(list)
def getDivision(n: Int): Int = total(0).no // 区分
def getTotal(n: Int): Int = total(0).value // 合計値
def createDivisionName(): AbstractDivisionName = new WholeDivisionName()
}
Main.scala object Main {
def main(args: Array[String]) {
val total: AbstractTotal = if (args(0) == "sub") {
new SubTotal()
}
else {
new WholeTotal()
}
total.operation()
val divisionName: AbstractDivisionName = total.createDivisionName()
System.out.println(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0))
}
}
|
Abstract Factoryパターンを使用した例 AbstractTotal.scala abstract class AbstractTotal {
protected var list = Seq(
// 区分 , 数値 (実際には DB などから数値を得る。)
new Data(1, 100), new Data(1, 500), new Data(1, 200),
new Data(2, 400), new Data(2, 200)
)
protected var total: Array[Data] = null // 合計値
def getDivision(n: Int): Int
def getTotal(n: Int): Int
def getSummary(): AbstractSummary
def operation() {
val sum: AbstractSummary = getSummary()
total = sum.calculateTotal()
}
}
SubTotal.scala class SubTotal extends AbstractTotal() {
def getSummary(): AbstractSummary = new SubTotalSummary(list)
def getDivision(n: Int): Int = total(n).no // 区分
def getTotal(n: Int): Int = total(n).value // 合計値
}
WholeTotal.scala class WholeTotal extends AbstractTotal() {
def getSummary(): AbstractSummary = new WholeTotalSummary(list)
def getDivision(n: Int): Int = new total(0).no // 区分
def getTotal(n: Int): Int = new total(0).value // 合計値
}
AbstractFactory.scala abstract class AbstractFactory {
def getTotal(): AbstractTotal
def getDivisionName(): AbstractDivisionName
}
SubFactory.scala class SubFactory extends AbstractFactory() {
override def getTotal(): AbstractTotal = new SubTotal()
override def getDivisionName(): AbstractDivisionName = new SubDivisionName()
}
WholeFactory.scala class WholeFactory extends AbstractFactory() {
override def getTotal(): AbstractTotal = new WholeTotal()
override def getDivisionName(): AbstractDivisionName = new WholeDivisionName()
}
Factory.scala class Factory(c: String) {
private var factory: AbstractFactory = if ("sub" == c) new SubFactory() else new WholeFactory()
def getFactory(): AbstractFactory = factory
}
Main.scala object Main {
def main(args: Array[String]) {
var factory = new Factory(args(0)).getFactory()
val total = factory.getTotal()
total.operation()
val divisionName = factory.getDivisionName()
System.out.println(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0))
}
}
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.groovy abstract class AbstractTotal {
// 区分 , 数値 (実際には DB などから数値を得る。)
protected Data[] list = [
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
]
protected Data[] total // 合計値
abstract int getDivision(int n)
abstract int getTotal(int n)
abstract AbstractSummary getSummary()
abstract AbstractDivisionName createDivisionName()
void operation() {
AbstractSummary sum = getSummary()
total = sum.calculateTotal()
}
}
SubTotal.groovy class SubTotal extends AbstractTotal {
AbstractSummary getSummary() {
return new SubTotalSummary(list)
}
int getDivision(int n) {
return total[n].no // 区分
}
int getTotal(int n) {
return total[n].value // 合計値
}
AbstractDivisionName createDivisionName() {
return new SubDivisionName()
}
}
WholeTotal.groovy class WholeTotal extends AbstractTotal {
WholeTotalSummary getSummary() {
return new WholeTotalSummary(list)
}
int getDivision(int n) {
return total[0].no // 区分
}
int getTotal(int n) {
return total[0].value // 合計値
}
AbstractDivisionName createDivisionName() {
return new WholeDivisionName()
}
}
Main.groovy class Main {
static void main(String[] args) {
AbstractTotal total = null
if ("sub" == args[0])
total = new SubTotal()
else
total = new WholeTotal()
total.operation()
AbstractDivisionName divisionName = total.createDivisionName()
System.out.println(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0))
}
}
|
Abstract Factoryパターンを使用した例 AbstractTotal.groovy abstract class AbstractTotal {
// 区分 , 数値 (実際には DB などから数値を得る。)
protected Data[] list = [
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
]
protected Data[] total // 合計値
abstract int getDivision(int n)
abstract int getTotal(int n)
abstract AbstractSummary getSummary()
void operation() {
AbstractSummary sum = getSummary()
total = sum.calculateTotal()
}
}
SubTotal.groovy class SubTotal extends AbstractTotal {
AbstractSummary getSummary() {
return new SubTotalSummary(list)
}
int getDivision(int n) {
return total[n].no // 区分
}
int getTotal(int n) {
return total[n].value // 合計値
}
}
WholeTotal.groovy class WholeTotal extends AbstractTotal {
WholeTotalSummary getSummary() {
return new WholeTotalSummary(list)
}
int getDivision(int n) {
return total[0].no // 区分
}
int getTotal(int n) {
return total[0].value // 合計値
}
}
AbstractFactory.groovy public abstract class AbstractFactory {
abstract AbstractTotal getTotal()
abstract AbstractDivisionName getDivisionName()
}
SubFactory.groovy class SubFactory extends AbstractFactory {
AbstractTotal getTotal() {
return new SubTotal()
}
AbstractDivisionName getDivisionName() {
return new SubDivisionName()
}
}
WholeFactory.groovy class WholeFactory extends AbstractFactory {
AbstractTotal getTotal() {
return new WholeTotal()
}
AbstractDivisionName getDivisionName() {
return new WholeDivisionName()
}
}
Factory.groovy class Factory {
private AbstractFactory factory
Factory() {}
Factory(String c) {
if ("sub" == c) {
factory = new SubFactory()
}
else {
factory = new WholeFactory()
}
}
AbstractFactory getFactory() {
return factory
}
}
Main.groovy class Main {
public static void main(String[] args) {
AbstractFactory factory = new Factory(args[0]).getFactory()
AbstractTotal total = factory.getTotal()
total.operation()
AbstractDivisionName divisionName = factory.getDivisionName()
System.out.println(divisionName.getName(total.getDivision(0)) + " " + total.getTotal(0))
}
}
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.go import "errors"
type ITotal interface {
GetDivision(int) int
GetTotal(int) int
CreateDivisionName() IDivisionName
GetSummary() ISummary
}
type IAbstractTotal interface {
ITotal
Operation(IAbstractTotal)
}
type AbstractTotal struct {
IAbstractTotal
list []*Data
total []*Data
}
func (*AbstractTotal) GetDivision(int) int {
panic(errors.New("GetDivision メソッドを定義してください。"))
return 0
}
func (*AbstractTotal) GetTotal(int) int {
panic(errors.New("GetTotal メソッドを定義してください。"))
return 0
}
func (*AbstractTotal) GetSummary() ISummary {
panic(errors.New("エラー:GetSummary メソッドを定義する必要があります。"))
return nil
}
func (*AbstractTotal) CalculateTotal() []*Data {
panic(errors.New("CalculateTotal メソッドを定義してください。"))
return nil
}
func (self *AbstractTotal) Operation(total ITotal) {
var sum = total.GetSummary()
self.total = sum.CalculateTotal()
}
func NewAbstractTotal() *AbstractTotal {
return &AbstractTotal {
list: []*Data {
// 区分 , 数値 (実際には DB などから数値を得る。)
NewData(1, 100),
NewData(1, 500),
NewData(1, 200),
NewData(2, 400),
NewData(2, 200),
},
}
}
SubTotal.go type SubTotal struct {
*AbstractTotal
}
func (self *SubTotal) GetSummary() ISummary {
return NewSubTotalSummary(self.list)
}
func (self *SubTotal) GetDivision(n int) int {
return self.total[n].no // 区分
}
func (self *SubTotal) GetTotal(n int) int {
return self.total[n].value // 合計値
}
func (self *SubTotal) CreateDivisionName() IDivisionName {
return NewSubDivisionName()
}
func NewSubTotal() IAbstractTotal {
var s IAbstractTotal
s = &SubTotal {
AbstractTotal: NewAbstractTotal(),
}
return s
}
WholeTotal.go type WholeTotal struct {
*AbstractTotal
}
func (self *WholeTotal) GetSummary() ISummary {
return NewWholeTotalSummary(self.list)
}
func (self *WholeTotal) GetDivision(n int) int {
return self.total[0].no // 区分
}
func (self *WholeTotal) GetTotal(n int) int {
return self.total[0].value // 合計値
}
func (self *WholeTotal) CreateDivisionName() IDivisionName {
return NewWholeDivisionName()
}
func NewWholeTotal() *IAbstractTotal {
var s IAbstractTotal
s = &WholeTotal {
AbstractTotal: NewAbstractTotal(),
}
return s
}
Main.go import (
"flag"
"fmt"
"strconv"
)
type main() {
flag.Parse()
var total IAbstractTotal = nil
if flag.Arg(0) == "sub" {
total = NewSubTotal()
} else {
total = NewWholeTotal()
}
total.Operation(total)
var div = total.CreateDivisionName()
fmt.Println(div.GetName(total.GetDivision(0)) + // 区分名
" " + strconv.Itoa(total.GetTotal(0))) // 合計値
}
|
Abstract Factoryパターンを使用した例 AbstractTotal.go import "errors"
type ITotal interface {
GetDivision(int) int
GetTotal(int) int
GetSummary() ISummary
}
type IAbstractTotal interface {
ITotal
Operation(IAbstractTotal)
}
type AbstractTotal struct {
IAbstractTotal
list []*Data
total []*Data
}
func (*AbstractTotal) GetDivision(int) int {
panic(errors.New("GetDivision メソッドを定義してください。"))
return 0
}
func (*AbstractTotal) GetTotal(int) int {
panic(errors.New("GetTotal メソッドを定義してください。"))
return 0
}
func (*AbstractTotal) GetSummary() ISummary {
panic(errors.New("エラー:GetSummary メソッドを定義する必要があります。"))
return nil
}
func (self *AbstractTotal) Operation(total ITotal) {
var sum = total.GetSummary()
self.total = sum.CalculateTotal()
}
func NewAbstractTotal() *AbstractTotal {
return &AbstractTotal {
list: []*Data {
// 区分 , 数値 (実際には DB などから数値を得る。)
NewData(1, 100),
NewData(1, 500),
NewData(1, 200),
NewData(2, 400),
NewData(2, 200),
},
}
}
SubTotal.go type SubTotal struct {
*AbstractTotal
}
func (self *SubTotal) GetDivision(n int) int {
return self.total[n].no // 区分
}
func (self *SubTotal) GetTotal(n int) int {
return self.total[n].value // 合計値
}
func (self *SubTotal) GetSummary() ISummary {
return NewSubTotalSummary(self.list)
}
func NewSubTotal() IAbstractTotal {
var s IAbstractTotal
s = &SubTotal {
AbstractTotal: NewAbstractTotal(),
}
return s
}
WholeTotal.go type WholeTotal struct {
*AbstractTotal
}
func (self *WholeTotal) GetDivision(n int)int {
return self.total[0].no // 区分
}
func (self *WholeTotal) GetTotal(n int) int {
return total[0].value // 合計値
}
func (self *WholeTotal) GetSummary() ISummary {
return new WholeTotalSummary(self.list)
}
func NewWholeTotal() IAbstractTotal {
var s IAbstractTotal
s = &WholeTotal {
AbstractTotal: NewAbstractTotal(),
}
return s
}
AbstractFactory.go import "errors"
type IFactory interface {
GetTotal() IAbstractTotal
GetDivisionName() IDivisionName
}
type AbstractFactory struct {
IFactory
}
func (*AbstractFactory) GetTotal() IAbstractTotal {
panic(errors.New("エラー:GetTotal メソッドを定義する必要があります。"))
return nil
}
func (*AbstractFactory) GetDivisionName() IDivisionName {
panic(errors.New("エラー:GetDivisionName メソッドを定義する必要があります。"))
return nil
}
SubFactory.go type SubFactory struct {
*AbstractFactory
}
func (*SubFactory) GetTotal() IAbstractTotal {
return NewSubTotal()
}
func (*SubFactory) GetDivisionName() IDivisionName {
return NewSubDivisionName()
}
func NewSubFactory() IFactory {
var s IFactory
s = &SubFactory {
AbstractFactory: new(AbstractFactory),
}
return s
}
WholeFactory.go type WholeFactory struct {
*AbstractFactory
}
func (*WholeFactory) GetTotal() IAbstractTotal {
return NewWholeTotal()
}
func (*WholeFactory) GetDivisionName() IDivisionName {
return NewWholeDivisionName()
}
func NewWholeFactory() IFactory {
var s IFactory
s = &WholeFactory {
AbstractFactory: new(AbstractFactory),
}
return s
}
Factory.go type Factory struct {}
func NewFactory(c string) IFactory {
var factory IFactory
if "sub" == c {
factory = NewSubFactory()
} else {
factory = NewWholeFactory()
}
return factory
}
Main.go import (
"flag"
"fmt"
"strconv"
)
func main() {
flag.Parse()
var factory = NewFactory(flag.Arg(0))
var total = factory.GetTotal()
total.Operation(total)
var divisionName = factory.getDivisionName()
fmt.Println(divisionName.GetName(total.GetDivision(0)) + // 区分名
" " + strconv.Itoa(total.getTotal(0))) // 合計値
}
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、GetFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 abstracttotal.d import data;
import abstractsummary;
import abstractdivisionname;
public abstract class AbstractTotal {
// 区分 , 数値 (実際には DB などから数値を得る。)
protected Data[] list = [
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
];
protected Data[] total; // 合計値
public abstract int getDivision(in int n);
public abstract int getTotal(in int n);
public abstract AbstractSummary getSummary();
public abstract AbstractDivisionName createDivisionName();
public void operation() {
AbstractSummary sum = getSummary();
total = sum.calculateTotal();
}
}
SubTotal.d import abstracttotal;
import abstractsummary;
import subtotalsummary;
import abstractdivisionname;
import subdivisionname;
public class SubTotal : AbstractTotal {
public override AbstractSummary getSummary() {
return new SubTotalSummary(list);
}
public override int getDivision(in int n) {
return total[n].no; // 区分
}
public override int getTotal(in int n) {
return total[n].value; // 合計値
}
public override AbstractDivisionName createDivisionName() {
return new SubDivisionName();
}
}
wholetotal.d import abstracttotal;
import abstractsummary;
import wholetotalsummary;
import abstractdivisionname;
import wholedivisionname;
public class WholeTotal : AbstractTotal {
public override WholeTotalSummary getSummary() {
return new WholeTotalSummary(list);
}
public override int getDivision(in int n) {
return total[0].no; // 区分
}
public override int getTotal(in int n) {
return total[0].value; // 合計値
}
public override AbstractDivisionName createDivisionName() {
return new WholeDivisionName();
}
}
main.d import abstracttotal;
import subtotal;
import wholetotal;
import abstractdivisionname;
public int main(string[] args) {
AbstractTotal total = null;
if (args[1] == "sub")
total = new SubTotal();
else
total = new WholeTotal();
total.operation();
AbstractDivisionName divisionName = total.createDivisionName();
printfln("%s %d", divisionName.getName(total.getDivision(0)), // 区分名
total.getTotal(0)); // 合計値
return 0;
}
private void printfln(T...)(T args) { // Shift JIS 出力
import std, std.windows.charset, core.vararg;
std.stdio.write(to!(string)(toMBSz(std.format.format(args))) ~ "\n");
}
|
Abstract Factoryパターンを使用した例 abstracttotal.d import abstractTotal;
import data;
import abstractSummary;
public abstract class AbstractTotal {
// 区分 , 数値 (実際には DB などから数値を得る。)
protected Data[] list = [
new Data(1, 100),
new Data(1, 500),
new Data(1, 200),
new Data(2, 400),
new Data(2, 200)
];
protected Data[] total; // 合計値
public abstract int getDivision(in int n);
public abstract int getTotal(in int n);
public abstract AbstractSummary getSummary();
public void operation() {
AbstractSummary sum = getSummary();
total = sum.calculateTotal();
}
}
subtotal.d import abstractTotal;
import abstractSummary;
import subTotalSummary;
public class SubTotal : AbstractTotal {
public override AbstractSummary getSummary() {
return new SubTotalSummary(list);
}
public override int getDivision(in int n) {
return total[n].no; // 区分
}
public override int getTotal(in int n) {
return total[n].value; // 合計値
}
}
wholetotal.d import abstractTotal;
import abstractSummary;
import wholeTotalSummary;
public class WholeTotal : AbstractTotal {
public override WholeTotalSummary getSummary() {
return new WholeTotalSummary(list);
}
public override int getDivision(in int n) {
return total[0].no; // 区分
}
public override int getTotal(in int n) {
return total[0].value; // 合計値
}
}
abstractfactory.d import abstractTotal;
import abstractDivisionName;
public abstract class AbstractFactory {
public abstract AbstractTotal getTotal();
public abstract AbstractDivisionName getDivisionName();
}
subfactory.d import abstractFactory;
import abstractTotal;
import abstractDivisionName;
import subTotal;
import subDivisionName;
public class SubFactory : AbstractFactory {
public override AbstractTotal getTotal() {
return new SubTotal();
}
public override AbstractDivisionName getDivisionName() {
return new SubDivisionName();
}
}
wholefactory.d import abstractFactory;
import abstractTotal;
import abstractDivisionName;
import wholeTotal;
import wholeDivisionName;
public class WholeFactory : AbstractFactory {
public override AbstractTotal getTotal() {
return new WholeTotal();
}
public override AbstractDivisionName getDivisionName() {
return new WholeDivisionName();
}
}
factory.d import abstractFactory;
import subFactory;
import wholeFactory;
public class Factory {
private AbstractFactory factory;
public this(in string c) {
if ("sub" == c) {
factory = new SubFactory();
}
else {
factory = new WholeFactory();
}
}
public AbstractFactory getFactory() {
return factory;
}
}
main.d import abstractFactory;
import factory;
import abstractTotal;
import abstractDivisionName;
public int main(string[] args)
{
AbstractFactory factory = new Factory(args[0]).getFactory();
AbstractTotal total = factory.getTotal();
total.operation();
AbstractDivisionName divisionName = factory.getDivisionName();
printfln("%s %d", divisionName.getName(total.getDivision(0)), // 区分名
total.getTotal(0)); // 合計値
return 0;
}
private void printfln(T...)(T args) { // Shift JIS 出力
import std, std.windows.charset, core.vararg;
std.stdio.write(to!(string)(toMBSz(std.format.format(args))) ~ "\n");
}
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |
共通クラス
|
Abstract Factoryパターンを使用しない例 AbstractTotal.pas unit UnitAbstractTotal;
interface
uses
UnitAbstractDivisionName,
UnitAbstractSummary,
UnitData;
type
AbstractTotal = class
protected
var list:TArrayOfData;
var total:TArrayOfData;
public
constructor Create();
destructor Destroy(); override;
function getDivision(n:integer):integer; virtual; abstract;
function getTotal(n:integer):integer; virtual; abstract;
function getSummary():AbstractSummary; virtual; abstract;
function createDivisionName():AbstractDivisionName; virtual; abstract;
procedure operation();
end;
implementation
constructor AbstractTotal.Create();
begin
list := [
Data.Create(1, 100),
Data.Create(1, 500),
Data.Create(1, 200),
Data.Create(2, 400),
Data.Create(2, 200)
];
end;
destructor AbstractTotal.Destroy();
var _data:Data;
begin
for _data in list do begin
_data.Free;
end;
end;
procedure AbstractTotal.operation();
var sum:AbstractSummary;
begin
sum := getSummary();
total := sum.calculateTotal();
end;
end.
SubTotal.pas unit UnitSubTotal;
interface
uses
UnitAbstractTotal,
UnitAbstractSummary,
UnitAbstractDivisionName,
UnitSubTotalSummary,
UnitSubDivisionName;
type
SubTotal = class(AbstractTotal)
public
function getSummary():AbstractSummary; override;
function getDivision(n:integer):integer; override;
function getTotal(n:integer):integer; override;
function createDivisionName():AbstractDivisionName; override;
end;
implementation
function SubTotal.getSummary():AbstractSummary;
begin
Result := SubTotalSummary.Create(list);
end;
function SubTotal.getDivision(n:integer):integer;
begin
Result := total[n].no; // 区分
end;
function SubTotal.getTotal(n:integer):integer;
begin
Result := total[n].value; // 合計値
end;
function SubTotal.createDivisionName():AbstractDivisionName;
begin
Result := SubDivisionName.Create();
end;
end.
WholeTotal.pas unit UnitWholeTotal;
interface
uses
UnitAbstractTotal,
UnitAbstractSummary,
UnitAbstractDivisionName,
UnitWholeTotalSummary,
UnitWholeDivisionName;
type
WholeTotal = class(AbstractTotal)
public
function getSummary():AbstractSummary; override;
function getDivision(n:integer:integer):integer; override;
function getTotal(n:integer:integer):integer; override;
function createDivisionName():AbstractDivisionName; override;
end;
implementation
function WholeTotal.getSummary():AbstractSummary;
begin
Result := WholeTotalSummary.Create(list);
end;
function WholeTotal.getDivision(n:integer):integer;
begin
Result := total[0].no; // 区分
end;
function WholeTotal.getTotal(n:integer):integer;
begin
Result := total[0].value; // 合計値
end;
function WholeTotal.createDivisionName():AbstractDivisionName;
begin
Result := WholeDivisionName.Create();
end;
end.
Main.dpr program Main;
uses
System.SysUtils,
UnitAbstractDivisionName,
UnitAbstractTotal,
UnitSubTotal,
UnitWholeTotal;
var total:AbstractTotal;
var divName:AbstractDivisionName;
begin
if ParamStr(1) = 'sub' then begin
total := SubTotal.Create();
end
else begin
total := WholeTotal.Create();
end;
total.operation();
divName := total.createDivisionName();
total.operation(); // 区分ごとの合計値算
Writeln(Format('%s %d', [divName.getName(total.getDivision(0)), // 区分名
total.getTotal(0)])); // 合計値
divName.Free;
total.Free;
end.
|
Abstract Factoryパターンを使用した例 AbstractTotal.pas unit UnitAbstractTotal;
interface
uses
UnitAbstractSummary,
UnitData;
type
AbstractTotal = class
protected
var list:TArrayOfData;
var total:TArrayOfData;
public
constructor Create();
destructor Destroy(); override;
function getDivision(n:integer):integer; virtual; abstract;
function getTotal(n:integer):integer; virtual; abstract;
function getSummary():AbstractSummary; virtual; abstract;
procedure operation();
end;
implementation
constructor AbstractTotal.Create();
begin
list := [
Data.Create(1, 100),
Data.Create(1, 500),
Data.Create(1, 200),
Data.Create(2, 400),
Data.Create(2, 200)
];
end;
destructor AbstractTotal.Destroy();
var _data:Data;
begin
for _data in list do begin
_data.Free;
end;
end;
procedure AbstractTotal.operation();
var sum:AbstractSummary;
begin
sum := getSummary();
total := sum.calculateTotal();
end;
end.
SubTotal.pas unit UnitSubTotal;
interface
uses
UnitAbstractTotal,
UnitAbstractSummary,
UnitSubTotalSummary;
type
SubTotal = class(AbstractTotal)
public
function getSummary():AbstractSummary; override;
function getDivision(n:integer):integer; override;
function getTotal(n:integer):integer; override;
end;
implementation
function SubTotal.getSummary():AbstractSummary;
begin
Result := SubTotalSummary.Create(list);
end;
function SubTotal.getDivision(n:integer):integer;
begin
Result := total[n].no; // 区分
end;
function SubTotal.getTotal(n:integer):integer;
begin
Result := total[n].value; // 合計値
end;
end.
WholeTotal.pas unit UnitWholeTotal;
interface
uses
UnitAbstractTotal,
UnitAbstractSummary,
UnitWholeTotalSummary;
type
WholeTotal = class(AbstractTotal)
public
function getSummary():AbstractSummary; override;
function getDivision(n:integer):integer; override;
function getTotal(n:integer):integer; override;
end;
implementation
function WholeTotal.getSummary():AbstractSummary;
begin
Result := WholeTotalSummary.Create(list);
end;
function WholeTotal.getDivision(n:integer):integer;
begin
Result := total[0].no; // 区分
end;
function WholeTotal.getTotal(n:integer):integer;
begin
Result := total[0].value; // 合計値
end;
end.
AbstractFactory.pas unit UnitAbstractFactory;
interface
uses
UnitAbstractTotal,
UnitAbstractDivisionName;
type
AbstractFactory = class
public
function getTotal():AbstractTotal; virtual; abstract;
function getDivisionName():AbstractDivisionName; virtual; abstract;
end;
implementation
end.
SubFactory.pas unit UnitSubFactory;
interface
uses
UnitAbstractFactory,
UnitAbstractTotal,
UnitSubTotal,
UnitAbstractDivisionName,
UnitSubDivisionName;
type
SubFactory = class(AbstractFactory)
public
function getTotal():AbstractTotal; override;
function getDivisionName():AbstractDivisionName; override;
end;
implementation
function SubFactory.getTotal():AbstractTotal;
begin
Result := SubTotal.Create();
end;
function SubFactory.getDivisionName():AbstractDivisionName;
begin
Result := SubDivisionName.Create();
end;
end.
WholeFactory.pas unit UnitWholeFactory;
interface
uses
UnitAbstractFactory,
UnitAbstractTotal,
UnitWholeTotal,
UnitAbstractDivisionName,
UnitWholeDivisionName;
type
WholeFactory = class(AbstractFactory)
public
function getTotal():AbstractTotal; override;
function getDivisionName():AbstractDivisionName; override;
end;
implementation
function WholeFactory.getTotal():AbstractTotal;
begin
Result := WholeTotal.Create();
end;
function WholeFactory.getDivisionName():AbstractDivisionName;
begin
Result := WholeDivisionName.Create();
end;
end.
Factory.pas unit UnitFactory;
interface
uses
UnitAbstractFactory,
UnitSubFactory,
UnitWholeFactory;
type
Factory = class
private
var factory:AbstractFactory;
public
constructor Create(c:string);
function getFactory():AbstractFactory;
end;
implementation
constructor Factory.Create(c:string);
begin
if c = 'sub' then
begin
factory := SubFactory.Create();
end
else
begin
factory := WholeFactory.Create();
end;
end;
function Factory.getFactory():AbstractFactory;
begin
Result := factory;
end;
end.
Main.dpr program Main;
uses
System.SysUtils,
UnitAbstractTotal,
UnitAbstractFactory,
UnitFactory,
UnitAbstractDivisionName;
var _factory:AbstractFactory;
var total:AbstractTotal;
var divName:AbstractDivisionName;
begin
_factory := Factory.Create(ParamStr(1)).getFactory();
total := _factory.getTotal();
total.operation();
divName := _factory.getDivisionName();
Writeln(Format('%s %d', [divName.getName(total.getDivision(0)), // 区分名
total.getTotal(0)])); // 合計値
divName.Free;
total.Free;
_factory.Free;
end.
|
|
Factory Method パターンで記述しています。 SubTotal クラスと WholeTotal クラスを利用しますが、そのクラス名を利用する側(main メソッド)で記述しています。この例では実行時に指定されたパラメータによって利用するクラス名を決定しています。もし、新たに別のクラスが追加されていくような場合、ユーザのソースを変更しなければなりません。 |
SubTotal クラスか、WholeTotal クラスか、どちらかのインスタンスを Factory というクラスのコンストラクタで生成しています(なお、この例では、SubDivisionName クラスか、WholeDivisionName クラスかも Factory クラスで生成しています)。もし、新たに別のクラスが追加されていくような場合でも、クラスの追加とともに Factory クラスを書き換えてあげればいいので、ユーザのソースを変更する必要はありません。 Factory Method パターンと Abstract Factory パターンとは似ていますが、これらパターンの違いは、この Factory クラスです。 main メソッドの中では、getFactory メソッドの戻り値の実際の型を知ることなく処理が進んでいます。すなわち、抽象的な factory インスタンスを利用して処理を進めていっているのです。このようにすることで、利用するオブジェクト群を入れ替えるということができます。 |