抽象工厂结构的差异

difference in structure of abstract factory

本文关键字:结构 工厂 抽象      更新时间:2023-10-16

我为抽象工厂编写了 2 种类型的代码:类型1 和类型2
类型1是我通过互联网
网站得出的,但类型2是我应该是一个更好的约定

类型1
首先是所需最终产品的基类。有必需的工厂基类。决定所需的工厂品牌。通过派生实例化它们的具体类。确定每个品牌的工厂应该提供哪些常见类别。然后通过推导实例化每个最终产品的最终产品的混凝土。但是在 main 函数中,您直接创建工厂对象。此类代码中将需要更多的维护。

class Shoe
{
public:
virtual void Detail() = 0;
char make[2];
int size;
};
class Shoe_B5:public Shoe //small
{
public:
Shoe_B5()
{
strcpy(make,"B");
size = 5;
}
void Detail()
{
cout<<"Shoe"<<make<<size<<endl;
}
};
class Shoe_B6:public Shoe //medium
{
public:
Shoe_B6()
{
strcpy(make,"B");
size = 6;
}
void Detail()
{
cout<<"Shoe"<<make<<size<<endl;
}
};
class Shoe_B7:public Shoe //large
{
public:
Shoe_B7()
{
strcpy(make,"B");
size = 7;
}
void Detail()
{
cout<<"Shoe"<<make<<size<<endl;
}
};
class Shoe_B8:public Shoe //XL
{
public:
Shoe_B8()
{
strcpy(make,"B");
size = 8;
}
void Detail()
{
cout<<"Shoe"<<make<<size<<endl;
}
};
class Shoe_RT5:public Shoe //small
{
public:
Shoe_RT5()
{
strcpy(make,"RT");
size = 5;
}
void Detail()
{
cout<<"Shoe"<<make<<size<<endl;
}
};

class Shoe_RT6:public Shoe //medium
{
public:
Shoe_RT6()
{
strcpy(make,"RT");
size = 6;
}
void Detail()
{
cout<<"Shoe"<<make<<size<<endl;
}
};
class Shoe_RT7:public Shoe //Large
{
public:
Shoe_RT7()
{
strcpy(make,"RT");
size = 7;
}
void Detail()
{
cout<<"Shoe"<<make<<size<<endl;
}
};

class Shoe_RT8:public Shoe //XL
{
public:
Shoe_RT8()
{
strcpy(make,"RT");
size = 8;
}
void Detail()
{
cout<<"Shoe"<<make<<size<<endl;
}
};
class Factory
{
public:
virtual Shoe* createSmall() = 0;
virtual Shoe* createMedium() = 0;
virtual Shoe* createLarge() = 0;
virtual Shoe* createXL() = 0;
};
class BataFactory: public Factory
{
public:
Shoe* createSmall()
{
return new Shoe_B5;
}
Shoe* createMedium()
{
return new Shoe_B6;
}
Shoe* createLarge()
{
return new Shoe_B7;
}
Shoe* createXL()
{
return new Shoe_B8;
}
};

class RedTapeFactory: public Factory
{
public:
Shoe* createSmall()
{
return new Shoe_RT5;
}
Shoe* createMedium()
{
return new Shoe_RT6;
}
Shoe* createLarge()
{
return new Shoe_RT7;
}
Shoe* createXL()
{
return new Shoe_RT8;
}
};
class Client
{
Factory* fac;
Shoe* s;
public:
Client(Factory* factory)
{
fac = factory;
}
Shoe* Create(int num)
{
switch(num)
{
case 1:
s = fac->createSmall();
break;
case 2:
s = fac->createMedium();
break;
case 3:
s = fac->createLarge();
break;
case 4:
s = fac->createXL();
break;
}
}
void getDetails()
{
s->Detail();
}
};
int main()
{
Factory * fac;
if(condition)
fac = new BataFactory;
else
fac = new RedTapeFactory;
Client * c = new Client(fac);
c->create(Size);
c->getDetails();
}

类型 2 的区别
但是在 main 函数中,您正在像在工厂方法中一样创建工厂。此类代码中所需的维护较少。

class Factory
{
public:
//produce allowed category of shoes
virtual Shoe* createSmall() = 0;
virtual Shoe* createMedium() = 0;
virtual Shoe* createLarge() = 0;
virtual Shoe* createXL() = 0;
//produce allowed category of factories
static Factory* CreateFactory(int num);
};
Factory* Factory::CreateFactory(int num)
{
switch(num)
{
case 1:
return new BataFactory;
break;
case 2:
return new RedTapeFactory;
break;
}
}
int main()
{
Factory * fac;
switch(condition)
{
case 1:
fac = Factory::CreateFactory(1);
break;
case 2:
fac = Factory::CreateFactory(2);
break;
}
Client * c = new Client(fac);
c->create(Size);
c->getDetails();
}

嗯,您正在使用new和原始指针来拥有自己的内存。这不应该在C++中完成。它总是会产生问题。

例如,在代码中,您永远不会删除此内存。这将导致内存泄漏。因此,请不要将new和原始指针用于拥有的记忆。将来使用"std::unique_ptr"或类似名称。

我还看到案例陈述。这也不是现代工厂变体的常用方法。您应该使用std::map,选择器作为键,函数指针作为值。

如果使用可变参数模板允许构造具有不同参数数的类,则可以增加更多的灵活性。

请参阅此处(众多(工厂实施的可能解决方案之一。

`#include <iostream>
#include <map>
#include <utility>
#include <any>

// Some demo classes ----------------------------------------------------------------------------------
struct Base {
Base(int d) : data(d) {};
virtual ~Base() { std::cout << "Destructor Basen"; }
virtual void print() { std::cout << "Print Basen"; }
int data{};
};
struct Child1 : public Base {
Child1(int d, std::string s) : Base(d) { std::cout << "Constructor Child1 " << d << " " << s << "n"; }
virtual ~Child1() { std::cout << "Destructor Child1n"; }
virtual void print() { std::cout << "Print Child1: " << data << "n"; }
};
struct Child2 : public Base {
Child2(int d, char c, long l) : Base(d) { std::cout << "Constructor Child2 " << d << " " << c << " " << l << "n"; }
virtual ~Child2() { std::cout << "Destructor Child2n"; }
virtual void print() { std::cout << "Print Child2: " << data << "n"; }
};
struct Child3 : public Base {
Child3(int d, long l, char c, std::string s) : Base(d) { std::cout << "Constructor Child3 " << d << " " << l << " " << c << " " << s << "n"; }
virtual ~Child3() { std::cout << "Destructor Child3n"; }
virtual void print() { std::cout << "Print Child3: " << data << "n"; }
};

using UPTRB = std::unique_ptr<Base>;

template <class Child, typename ...Args>
UPTRB createClass(Args...args) { return std::make_unique<Child>(args...); }
// The Factory ----------------------------------------------------------------------------------------
template <class Key, class Object>
class Factory
{
std::map<Key, std::any> selector;
public:
Factory() : selector() {}
Factory(std::initializer_list<std::pair<const Key, std::any>> il) : selector(il) {}
template<typename Function>
void add(Key key, Function&& someFunction) { selector[key] = std::any(someFunction); };
template <typename ... Args>
Object create(Key key, Args ... args) {
if (selector.find(key) != selector.end()) {
return std::any_cast<std::add_pointer_t<Object(Args ...)>>(selector[key])(args...);
}
else return nullptr;
}
};
int main()
{
// Define the factory with an initializer list
Factory<int, UPTRB> factory{
{1, createClass<Child1, int, std::string>},
{2, createClass<Child2, int, char, long>}
};
// Add a new entry for the factory
factory.add(3, createClass<Child3, int, long, char, std::string>);

// Some test values
std::string s1(" Hello1 "); std::string s3(" Hello3 ");
int i = 1;  const int ci = 1;   int& ri = i;    const int& cri = i;   int&& rri = 1;
UPTRB b1 = factory.create(1, 1, s1);
UPTRB b2 = factory.create(2, 2, '2', 2L);
UPTRB b3 = factory.create(3, 3, 3L, '3', s3);
b1->print();
b2->print();
b3->print();
b1 = factory.create(2, 4, '4', 4L);
b1->print();
return 0;
}