2015-01-22 4 views
0

У меня есть некоторый код, как:шаблона дизайна для следующей ситуации

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() ... конструкции, а также использовать некоторые более обобщенные модели, но я до сих пор не сделал менеджер придумайте что-нибудь полезное. Есть ли лучший способ сделать это?

+0

Вы знаете, что ваш пример кода имеет ужасную ошибку? – Dainius

+0

Да, но это больше похоже на псевдокод C++, а не на то, что вы действительно хотите скомпилировать и использовать. – fritzone

ответ

4

Если вы хотите факторизовать код, у вас есть несколько производных классов, вы можете использовать что-то вроде следующего:

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.

+0

Это замечательный фрагмент кода. К сожалению, у меня нет доступа к C++ 14 (или C++ 11) ... потому что древние компиляторы используются в наших средах разработки (поскольку производственная среда тоже древняя :)) Независимо от этого, ответ принят и я назову этот шаблон AcceptorFactory :) – fritzone

0

Вы создаете свои объекты. Factory или Builder - подходящие шаблоны для вас.

+0

Ухм, он уже использует заводскую модель. Только он хочет его упростить. – RvdK

+0

@RvdK Поскольку acceptsData принимает время выполнения решения, ему нужно, если что-то еще. Если он по умолчанию знает, какой класс принимает данные, он может создавать каждый класс для разных типов данных. Я имею в виду, как это: Base * createStuff (тип DataFormat) { \t переключатель (тип) { \t \t случай типа1: \t \t \t новый CType1Acceptor; \t \t case type2: \t \t \t новый CType1Acceptor; \t} } – CreativeMind

0

Что может удовлетворить ваши требования, так это то, что виртуальные конструкторы создают шаблон. Это то, на что это похоже ...

#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; 
} 
+0

Вы намеревались использовать 'strcmp' вместо' operator == 'с' char * '? – user2079303

+0

Да, спасибо, спасибо. – dspfnder

+0

@dspfnder Извините, но я не ищу простой завод здесь. Я ищу Factory, который создает объекты на основе входных данных, которые будут принимать эти объекты. – fritzone

Смежные вопросы