1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

デザインパターン_AbstractFactory

Last updated at Posted at 2022-11-09

初めに

この記事は実力不足により,作成途中です.
改善案等がありましたら,是非コメントしてください.

参照

8.AbstractFactoryパターン
実践デザパタ-その2:Factory Methodパターン
IT専科-Abstract Factory パターン

開発環境

windows10 home
C++20
VisualStudio2019

AbstractFactoryパターンとは

AbstractFactoryパターンとは,生成に関するデザインパターンの1つで,
Factoryパターンと同様に一連のオブジェクト群を間違いなく生成するためのパターンになっている.

例えば、「車」を作成するプログラムを考えてみてください。このプログラムのある部分で、
「車」オブジェクトである変数carにタイヤとハンドルを追加しています。
car.addTire(new CarTire());
car.addHandle(new CarHandle());
このプログラムの書き方は、たいていの場合問題ないのですが、プログラマーのふとしたミスで、
とんでもない間違いが起きる可能性があります。例えば、車を作っているのに、
自転車のタイヤを渡してしまうようなことを考えて見ましょう。
car.addTire(new BicycleTire());
car.addHandle(new CarHandle());
まさか実際に車を作成するときに、このような間違いを犯してしまうことは考えられません。
しかし、利用すべきでないオブジェクトを利用してしまう可能性は大いに考えられます。
このようなとき、車を作成するために必要な一連のオブジェクトを作成することを
一手に引き受ける工場クラスを用意し、タイヤやハンドルといったオブジェクトを生成するときは、
この工場クラスを利用してオブジェクトの生成を行うようにすることで、
先ほどのような間違いが起こることを回避することができます。
また、この工場クラスを変更することで、利用する一連のオブジェクトをごっそり変更することもできるようになります。

8.AbstractFactoryパターンより引用

メリット

  • 変更がしやすくなる
  • 複雑な生成処理が分かりやすくなる
  • 結合度が低い

デメリット

逆に、Abstract Factoryパターンの欠点は、
関連オブジェクト(先ほどの例だと「ブラウザ」「ファイルシステム」)の種類が増えた場合、
修正箇所がすべてのFactoryクラスに及んでしまう点です。この場合だと、開放・閉鎖原則は守られていません。

実践デザパタ-その2:Factory Methodパターンより引用

処理

クラス図

designpattern-abstract_factory01.gif
IT専科-Abstract Factory パターンより引用

main

main.cpp
#include "AbstractFactory.h"
using namespace std;

int main()
{
    auto factory = std::make_unique<AbstractFactory<ConcreteFactory>>();

    //TODO:ここはメモリの局所性が悪い気がする
    auto product_a = factory->Use()->create_product_a();
    product_a->do_something();

    auto product_b = factory->Use()->create_product_b();
    product_b->do_something();

    return 0;
}

AbstractFactory

ConcreteFactory
#pragma once
#include "ConcreteProduct.h"

// Factoryを表すインタフェース
template<class T>
concept FactoryConcept = requires(T obj) {
    {obj.create_product_a()}->std::convertible_to<std::unique_ptr<Product>>;
    {obj.create_product_b()}->std::convertible_to<std::unique_ptr<Product>>;
};


template<FactoryConcept T>
class AbstractFactory
{
public:
    AbstractFactory() {}
    virtual ~AbstractFactory() {};
    std::unique_ptr<T> Use() { return std::make_unique<T>(); }
};


//TODO:AbstractFactoryから派生させたい
class ConcreteFactory
{
public:
    ConcreteFactory() {};
    ~ConcreteFactory() {};
    std::unique_ptr<Product> create_product_a() const
    {
        return std::make_unique<ConcreteProductA>();
    }

    std::unique_ptr<Product> create_product_b() const
    {
        return std::make_unique<ConcreteProductB>();
    }
};

Product

Product.h
#pragma once

#include <iostream>
#include <memory>
#include <concepts>

class Product
{
public:
    virtual ~Product() = default;
    virtual void do_something() const = 0;
};

ConcreteProduct

ConcreteProduct.h
#pragma once
#include "Product.h"

class ConcreteProductA : public Product
{
public:
    void do_something() const override
    {
        std::cout << "ConcreteProductA: doing something" << std::endl;
    }
};

class ConcreteProductB : public Product
{
public:
    void do_something() const override
    {
        std::cout << "ConcreteProductB: doing something" << std::endl;
    }
};

改良したいところ

上記のTODOにもある通り

  • 局所性の改善
  • ConcreteFactoryをAbstractFactoryから派生するようにしてミスする可能性を減らす
    を改良したいです.
1
0
0

Register as a new user and use Qiita more conveniently

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?