[Design pattern] 1-4. デザインパターンの抽象ファクトリーパターン(Abstract factory pattern)
こんにちは。明月です。
この投稿はデザインパターンの抽象ファクトリーパターン(Abstract factory pattern)に関する説明です。
デザインパターンの生成パターンの中で一番複雑なパターンの抽象ファクトリーパターン(Abstract factory pattern)です。
構造は複雑ですが、細かく見るとファクトリーメソッドパターンでファクトリーをクラスで作成してその上に抽象インターフェースによりファクトリーを取得するし、そのファクトリーでクラスを取得する構造です。
つまり、ファクトリーメソッドパターンが重畳していると思えば良いです。
#pragma once
#include <stdio.h>
#include <iostream>
using namespace std;
// 抽象クラス
class IDao {
public:
// 抽象メソッド
virtual string getData() = 0;
};
// 抽象ファクトリーメソッド
class IFactory {
public:
// 抽象メソッド (IDao タイプのクラスをリターンする。)
virtual IDao* getTypeDao() = 0;
};
// ATypeDAO クラス, IDao 抽象クラスを継承
class ATypeDAO : public IDao {
public:
// 関数再定義
virtual string getData() {
// string値をリターン
return "ATypeDAO - getData()";
}
};
// ファクトリークラス, IFactory 抽象ファクトリーメソッドを継承
class AFactory : public IFactory {
public:
// 関数再定義してATypeDAOクラスのインスタンスをリターンする。 클래스의 인스턴스를 리턴한다.
virtual IDao* getTypeDao() {
return new ATypeDAO();
}
};
// BTypeDAOクラス, IDao 抽象クラスを継承
class BTypeDAO : public IDao {
public:
// 関数再定義
virtual string getData() {
// string値をリターン
return "BTypeDAO - getData()";
}
};
// ファクトリークラス, IFactory 抽象ファクトリーメソッドを継承
class BFactory : public IFactory {
public:
// 関数再定義して BTypeDAO クラスのインスタンスをリターンする。
virtual IDao* getTypeDao() {
return new BTypeDAO();
}
};
// ファクトリーパターン、パラメータの値によりファクトリークラスのインスタンスをリターンする。
IFactory* getFactory(int type) {
// 0の値ならAFactoryクラスのインスタンスをリターン
if (type == 0) {
return new AFactory();
}
// 0の値ではないならBFactoryクラスのインスタンスをリターン
else {
return new BFactory();
}
}
// 実行関数
int main() {
// ファクトリー関数からファクトリーインスタンスを取得する。
IFactory* factory = getFactory(0);
// 関数を通ってATypeDAOクラスのインスタンスを受け取る。(ここではビルドパターン(ここでまたファクトリーパターンを入れても良い))
IDao* dao = factory->getTypeDao();
// コンソールに出力
cout << dao->getData() << endl;
// メモリ解除
delete dao;
delete factory;
// ファクトリー関数からファクトリーインスタンスを取得する。
factory = getFactory(1);
// 関数を通ってBTypeDAOクラスのインスタンスを受け取る。(ここではビルドパターン(ここでまたファクトリーパターンを入れても良い))
dao = factory->getTypeDao();
// コンソールに出力
cout << dao->getData() << endl;
// メモリ解除
delete dao;
delete factory;
return 0;
}
上の例をみればFactoryクラスをgetFactoryという関数からインスタンスを受け取ります。
また、FactoryクラスにはgetTypeDaoを通ってインスタンスを受け取ります。私はここでビルドパターンを通ってIDaoを受け取りますが、getTypeDaoにパラメータを入れてまたファクトリーメソッドパターンを使えます。
// 実行関数があるクラス
public class Program {
// ファクトリーメソッドパターンでファクトリークラスを受け取る。
private static IFactory getFactory(String type) {
// 入力値がAならAFactoryクラスのインスタンスをリターン
if ("A".equals(type.toUpperCase())) {
return new AFactory();
// 入力値がBならBFactoryクラスのインスタンスをリターン
} else if ("B".equals(type.toUpperCase())) {
return new BFactory();
}
// 条件に合わなかったらnull
return null;
}
// 実行関数
public static void main(String[] args) {
// ファクトリーメソッドパターンでファクトリークラスを受け取る。
var factory = getFactory("A");
// ここでまたgetType関数を通ってAType1Daoクラスのインスタンスを受け取ってgetData()関数のリターン値をコンソールに出力
System.out.println(factory.getTypeDao(1).getData());
// ここでまたgetType関数を通ってAType2Daoクラスのインスタンスを受け取ってgetData()関数のリターン値をコンソールに出力
System.out.println(factory.getTypeDao(2).getData());
// ファクトリーメソッドパターンでファクトリークラスを受け取る。
factory = getFactory("B");
// ここでまたgetType関数を通ってBType1Daoクラスのインスタンスを受け取ってgetData()関数のリターン値をコンソールに出力
System.out.println(factory.getTypeDao(1).getData());
// ここでまたgetType関数を通ってBType2Daoクラスのインスタンスを受け取ってgetData()関数のリターン値をコンソールに出力
System.out.println(factory.getTypeDao(2).getData());
}
}
// インターフェース
interface IDao {
// 最終クラスから受け取ったデータ
String getData();
}
// 抽象ファクトリーメソッドインターフェース
interface IFactory {
// ここもファクトリーメソッドパターンを通ってIDaoクラスのインスタンスを受け取る。
IDao getTypeDao(int type);
}
// AType1Daoクラス、IDaoインターフェースを継承
class AType1Dao implements IDao {
// 関数再定義
@Override
public String getData() {
// 結果値をリターン
return "AType1Dao - getData()";
}
}
// AType2Daoクラス、IDaoインターフェースを継承
class AType2Dao implements IDao {
// 関数再定義
@Override
public String getData() {
// 結果値をリターン
return "AType2Dao - getData()";
}
}
// ファクトリークラス, IFactory 인터페이스를 상속
class AFactory implements IFactory {
// 関数再定義
@Override
// ファクトリーメソッドパターンを通ってIDaoタイプのクラスを取得
public IDao getTypeDao(int type) {
// 値が1ならAType1Daoクラスのインスタンスをリターン
if (type == 1) {
return new AType1Dao();
// 値が2ならAType2Daoクラスのインスタンスをリターン
} else if (type == 2) {
return new AType2Dao();
}
// 条件に合わなかったらnull
return null;
}
}
// BType1Daoクラス、IDaoインターフェースを継承
class BType1Dao implements IDao {
// 関数再定義
@Override
public String getData() {
// 結果値をリターン
return "BType1Dao - getData()";
}
}
// BType2Daoクラス、IDaoインターフェースを継承
class BType2Dao implements IDao {
// 関数再定義
@Override
public String getData() {
// 結果値をリターン
return "BType2Dao - getData()";
}
}
// ファクトリークラス, IFactoryインターフェースを継承
class BFactory implements IFactory {
// 関数再定義
@Override
// ファクトリーメソッドパターンを通ってIDaoタイプのクラスを取得
public IDao getTypeDao(int type) {
// 値が1ならBType1Daoクラスのインスタンスをリターン
if (type == 1) {
return new BType1Dao();
// 値が2ならBType2Daoクラスのインスタンスをリターン
} else if (type == 2) {
return new BType2Dao();
}
// 条件に合わなかったらnull
return null;
}
}
上の例はJavaで作成した抽象ファクトリーパターン例です。
C/C++と違い、ファクトリークラスの中でビルドパターンを代わりにファクトリーメソッドパターンでインスタンスを取得します。
using System;
namespace Example
{
// インターフェース
interface IDao
{
// コンソールに出力
void Print();
}
// 抽象ファクトリーメソッドインターフェース
interface IFactory
{
// 抽象メソッド (IDao タイプのクラスをリターンする。)
IDao GetTypeDao();
}
// ATypeDAOクラス、IDao 抽象クラスを継承
class ATypeDao : IDao
{
// コンソールに出力する関数
public void Print()
{
// コンソールに出力
Console.WriteLine("ATypeDao - GetData()");
}
}
// ファクトリークラス, IFactory 抽象ファクトリーメソッドを継承
class AFactory : IFactory
{
// ATypeDaoクラスのインスタンスをリターン
public IDao GetTypeDao()
{
// ATypeDaoクラスインスタンスを生成
return new ATypeDao();
}
}
// BTypeDAOクラス、IDao 抽象クラスを継承
class BTypeDao : IDao
{
// コンソール出力関数
public void Print()
{
// コンソール出力
Console.WriteLine("BTypeDao - GetData()");
}
}
// ファクトリークラス, IFactory 抽象ファクトリーメソッドを継承
class BFactory : IFactory
{
// BTypeDaoクラスのインスタンスをリターン
public IDao GetTypeDao()
{
// BTypeDaoクラスのインスタンスを生成
return new BTypeDao();
}
}
// 実行関数があるクラス
public class Program
{
// ファクトリーメソッドパターンでファクトリークラスのインスタンスを取得する関数
private static IFactory GetFactory(String type)
{
// パラメータ値がAの場合
if ("A".Equals(type, StringComparison.OrdinalIgnoreCase))
{
// AFactoryクラスのインスタンスを生成してリターン
return new AFactory();
}
// パラメータ値がBの場合
else if ("B".Equals(type, StringComparison.OrdinalIgnoreCase))
{
// BFactoryクラスのインスタンスを生成してリターン
return new BFactory();
}
// 条件に合わなかったらnull
return null;
}
// 実行関数
public static void Main(string[] args)
{
// ファクトリーメソッドパターンの関数でファクトリーを取得する。
var factory = GetFactory("A");
// 取得したファクトリーでATypeDaoインスタンスのPrint関数を実行
factory.GetTypeDao().Print();
// ファクトリーメソッド関数でファクトリーを取得する。
factory = GetFactory("B");
// 取得したファクトリーでBTypeDaoインスタンスのPrint関数を実行
factory.GetTypeDao().Print();
// 任意のキーを押してください
Console.WriteLine("Press Any key...");
Console.ReadLine();
}
}
}
上の例はC/C++と同じく、ファクトリークラスでビルドパターンでインスタンスを取得して実行します。
私がFactoryクラスではなく、一般クラスをDaoというクラス名で作成しました。
なぜならこの抽象ファクトリーパターンがORMフレームワークで一番よく使うパターンからです。
例えば、データベースの各テーブルのDaoクラスを作成します。でも、仕様によりこれがOracleになれるし、Mssqlになれるし、Mysql(MariaDB)になれる可能性があります。
各データベースのシステムのテーブルの設計構造は同じだと思えば、この抽象ファクトリーパターンを使ったらOracle用Dao生成ファクトリーを生成することができるし、Mssql用Dao生成ファクトリーを生成することができます。
その以外にデータ管理や生成、PDF生成やExcel生成などで仕様により装置を区分する時、該当なクラスの構造は同じく作ろうと思えば、よく使えるパターンです。
ここまでデザインパターンの抽象ファクトリーパターン(Abstract factory pattern)に関する説明でした。
ご不明なところや間違いところがあればコメントしてください。
- [Design pattern] 3-2. 責任の連鎖パターン(Chain of responsibility pattern)2021/11/04 19:27:58
- [Design pattern] 3-1. ストラテジーパターン(Strategy pattern)2021/11/03 18:38:52
- [Design pattern] 2-7. ファサードパターン(Facade pattern)2021/11/02 19:32:31
- [Design pattern] 2-6. プロキシパターン(Proxy pattern)2021/11/01 19:42:44
- [Design pattern] 2-5. フライウェイトパターン(Flyweight pattern)2021/10/29 19:48:27
- [Design pattern] 2-4. デコレーターパターン(Decorator pattern)2021/10/28 20:11:13
- [Design pattern] 2-3. ブリッジパターン(Bridge pattern)2021/10/27 20:32:21
- [Design pattern] 2-2. コンポジットパターン(Composite pattern)2021/10/27 20:30:54
- [Design pattern] 2-1. アダプターパターン(Adapter pattern)2021/10/26 19:12:40
- [Design pattern] 1-5. プロトタイプパターン(Prototype pattern)2021/10/22 19:35:45
- [Design pattern] 1-4. デザインパターンの抽象ファクトリーパターン(Abstract factory pattern)2021/10/15 19:31:03
- [Design pattern] 1-3. ファクトリーメソッドパターン(Factory method pattern)2021/06/23 19:45:37
- [Design pattern] 1-2. ビルダーパターン(Builder pattern)2021/06/11 19:06:28
- [Design pattern] 1-1. シングルトンパターン(Singleton pattern)2021/06/09 19:40:05
- [Design Pattern] デザインパターンの紹介2021/06/08 20:42:36
- check2024/04/10 19:03:53
- [Java] 64.Spring bootとReactを連結する方法(Buildする方法)2022/03/25 21:02:18
- [Javascript] Node.jsをインストールしてReactを使う方法2022/03/23 18:01:34
- [Java] 63. Spring bootでcronスケジューラとComponentアノテーション2022/03/16 18:57:30
- [Java] 62. Spring bootでWeb-Filterを設定する方法(Spring Security)2022/03/15 22:16:37
- [Java] JWT(Json Web Token)を発行、確認する方法2022/03/14 19:12:58
- [Java] 61. Spring bootでRedisデータベースを利用してセッションクラスタリング設定する方法2022/03/01 18:20:52
- [Java] 60. Spring bootでApacheの連結とロードバランシングを設定する方法2022/02/28 18:45:48
- [Java] 59. Spring bootのJPAでEntityManagerを使い方2022/02/25 18:27:48
- [Java] 58. EclipseでSpring bootのJPAを設定する方法2022/02/23 18:11:10
- [Java] 57. EclipseでSpring bootを設定する方法2022/02/22 19:04:49
- [Python] Redisデータベースに接続して使い方2022/02/21 18:23:49
- [Java] Redisデータベースを接続して使い方(Jedisライブラリ)2022/02/16 18:13:17
- [C#] Redisのデータベースを接続して使い方2022/02/15 18:46:09
- [CentOS] Redisデータベースをインストールする方法とコマンドを使い方2022/02/14 18:33:07