【问题标题】:A Design pattern for the following situation针对以下情况的设计模式
【发布时间】:2015-01-22 11:32:25
【问题描述】:

我有一些类似的代码:

class Base {
    virtual bool acceptsData(char*) = 0;
};

class Derived1 : public Base {
    virtual bool acceptsData(char*) { /* do something */ }
};

class Derived2 : public Base {
    virtual bool acceptsData(char*) { /* do something else */}
}

Base* createStuff(char* data)
{
    Base* d1 = new Derived1();
    if(d1->acceptsData(data))
    {
          return d1;
    }
    delete d1;

    Base* d2 = new Derived2();
    if(d2->acceptsData(data))
    {
          return d2;
    }
    delete d2;
     // and more ...
}
// .... somewhere later
int main()
{
    Base* Aclass = createStuff("abc");
}

我想摆脱这个冗长的if() ... 构造,并使用一些更通用的模式,但我仍然没有经理想出一些有用的东西。有更好的方法吗?

【问题讨论】:

  • 你知道你的示例代码有可怕的错误吗?
  • 是的,但它的目的更多是作为 c++ 伪代码,而不是您真正想要编译和使用的东西。

标签: c++ design-patterns factory


【解决方案1】:

如果你想分解代码,因为你有几个派生类,你可以使用类似下面的东西:

namespace detail
{
    template <typename T> std::unique_ptr<Base> make_base(const char* data)
    {
        std::unique_ptr<Base> base = std::make_unique<T>();
        if (base->acceptsData(data)) {
            return base;
        }
        return nullptr;
    }

    template <typename... Ts> std::unique_ptr<Base> createStuff(const char* data)
    {
        std::function<std::unique_ptr<Base>(const char*)> fs[] = { make_base<Ts>... };

        for(auto& f : fs) {
            auto base = f(data);
            if(base) {
                return base;
            }
        }
        return nullptr;
    }
}

Base* createStuff(const char* data) {
    return detail::createStuff<Derived1, Derived2/* and other Derived classes*/>(data).release();
}

Live example.

【讨论】:

  • 这是一段了不起的代码。不幸的是,我无法访问 c++14(也没有 c++11)......因为我们的开发环境中使用了古老的编译器(因为生产环境也很古老:))无论如何,答案都被接受了我将这种模式称为 AcceptorFactory :)
【解决方案2】:

你正在创建你的对象。 Factory 或 Builder 是适合您的模式。

【讨论】:

  • 嗯,他已经在使用工厂模式了。只有他想简化它。
  • @RvdK 由于 acceptData 正在决定运行时,他需要 if else ..如果他知道默认情况下哪个类接受数据,他可以为不同类型的数据创建每个类。我的意思是这样的: Base* createStuff(DataFormat type) { switch( type ){ case type1: new CType1Acceptor;案例类型2:新的CType1Acceptor; } }
【解决方案3】:

可能满足您要求的是虚拟构造函数设计模式。就是这个样子……

#include <iostream>
#include <string>    
#include <vector>
using namespace std;
class Base {
    Base* b;
    // suppress the usual constructors
    Base(Base&);
    Base operator=(Base&);
protected:
    Base() { b = 0; };
public:
    virtual void Print() { b->Print(); }    
    virtual ~Base() {       
        if (b) {            
            delete b;
        }       
    }   
    Base(string type);
};
class Derived1 : public Base {
    Derived1(Derived1&);
    Derived1 operator=(Derived1&);
    Derived1() {} 
    friend class Base;
public:
    void Print() { cout << "Derived1::Print()" << endl; }
    ~Derived1() { }
};
class Derived2 : public Base {
    Derived2(Derived2&);
    Derived2 operator=(Derived2&);
    Derived2() {}
    friend class Base;
public:
    void Print() { cout << "Derived2::Print()" << endl; }   
    ~Derived2() { }
};
Base::Base(string type) {
    if (type == "Derived1")
        b = new Derived1;
    else if (type == "Derived2")
        b = new Derived2;   
}

int main() {
    vector<Base*> bases;
    cout << "virtual constructor calls:" << endl;
    bases.push_back(new Base("Derived2"));
    bases.push_back(new Base("Derived1"));
    bases.push_back(new Base("Derived1"));
    bases.push_back(new Base("Derived2"));

    for (int i = 0; i < bases.size(); i++) {
        bases[i]->Print();      
    }

    cout << "destructor calls:" << endl;
    for (int j = 0; j < bases.size(); j++) {
        delete bases[j];        
    }

    // system("pause");
    return 0;
}

【讨论】:

  • 您是否打算在char* 中使用strcmp 而不是operator==
  • @dspfnder 对不起,我不是在这里寻找一个简单的工厂。我正在寻找一个工厂,它根据这些对象将接受的输入数据创建对象。
  • 这个工厂的名字是Virtual Constructors。它模拟一个虚拟构造函数。
猜你喜欢
  • 2014-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-18
相关资源
最近更新 更多