From What are the differences between Abstract Factory and Factory design patterns?:
Factory
Imagine you are constructing a house and you approach a carpenter for a door. You give the measurement for the door and your requirements, and he will construct a door for you. In this case, the carpenter is a factory of doors. Your specifications are inputs for the factory, and the door is the output or product from the factory.
Abstract Factory
Now, consider the same example of the door. You can go to a carpenter, or you can go to a plastic door shop or a PVC shop. All of them are door factories. Based on the situation, you decide what kind of factory you need to approach. This is like an Abstract Factory.
According to that explanation, is the following code a factory method or an abstract factory pattern?
class PaintShape
{
public:
static PaintShape *createShapeObject( std::string shape );
virtual void print() { std::cout << "print PaintShape"; }
};
class PaintTriangle : public PaintShape
{
public:
PaintTriangle() {}
virtual void print() { std::cout << "\nprint PaintTriangle"; }
};
class PaintRectangle : public PaintShape
{
public:
PaintRectangle() {}
virtual void print() { std::cout << "\nprint PaintRectangle"; }
};
PaintShape* PaintShape::createShapeObject( std::string shape )
{
if( shape == "triangle" )
return new PaintTriangle;
else if( shape == "rectangle" )
return new PaintRectangle;
return new PaintShape;
};
class EndDeveloper
{
public:
EndDeveloper()
{
std::string shape;
std::cout << "\nWhat shape would you like? ";
// Get input from the terminal.
std::getline( std::cin, shape );
PaintShape *p = PaintShape::createShapeObject( shape );
p->print();
std::cout << "\nWhat shape would you like? ";
std::getline (std::cin, shape);
PaintShape *s = PaintShape::createShapeObject( shape );
s->print();
}
};
What would be the way to convert this into a factory method and/or an abstract factory method?
According to that explanation, is the following code a factory method or an abstract factory pattern?
That code is not an implementation of either pattern:
What would be the way to convert this into a factory method?
Assuming we must use the factory method, we have to introduce a class responsible for creating shapes. To add to the confusion, these will be of type ShapeFactory, but don't take this as an implementation of the Abstract Factory pattern. It is not.1
Here, our client interacts with a ShapeFactory by calling its createShape() method, the factory method. Subclasses override this method and return the proper Shape. This is what the factory method pattern is about: deferring creation to subclasses.
#include <iostream>
class Shape {
public:
virtual std::string text() = 0;
virtual double area() = 0;
};
class Rectangle : public Shape {
public:
std::string text() override { return "rectangle"; }
double area() override { return 1.0; }
};
class Triangle : public Shape {
public:
std::string text() override { return "triangle"; }
double area() override { return 2.0; }
};
class ShapeFactory {
public:
virtual Shape* createShape() = 0;
};
class RectangleFactory : public ShapeFactory {
public:
Shape* createShape() override {
return new Rectangle();
}
};
class TriangleFactory : public ShapeFactory {
public:
Shape* createShape() override {
return new Triangle();
}
};
ShapeFactory* makeShapeFactory(std::string shape) {
if (shape == "triangle") {
return new TriangleFactory();
} else {
return new RectangleFactory();
}
};
int main() {
// Get input from the terminal.
std::string shape;
std::cout << "What shape would you like? ";
std::getline(std::cin, shape);
ShapeFactory* p = makeShapeFactory(shape);
Shape* s = p->createShape();
std::cout << s->text() << std::endl;
delete p;
delete s;
return 0;
}
I would be grateful if you could add the implementation of abstract factory method too.
A ShapeFactory can now create two-dimensional or three-dimensional shapes. Now we have two disjoint class hierarchies: TwoDShape and ThreeDShape. However, we want clients to use the proper 2D and 3D subclasses. There is an implicit relationship here and it would be better if we can state that explicitly in code. This is what the Abstract Factory pattern is about: enforcing relationships.
Now our ShapeFactory has two Factory methods: create2dShape() and create3dShape(). When a client interacts with a ShapeFactory, they are bound to the proper TwoDShape and ThreeDShape classes. For example, a RectangleFactory factory creates TwoDRectangles and ThreeDRectangles.
#include <iostream>
class TwoDShape {
public:
virtual std::string text() = 0;
virtual double area() = 0;
};
class TwoDRectangle : public TwoDShape {
public:
std::string text() override { return "2d rectangle"; }
double area() override { return 1.0; }
};
class TwoDTriangle : public TwoDShape {
public:
std::string text() override { return "2d triangle"; }
double area() override { return 2.0; }
};
class ThreeDShape {
public:
virtual std::string text() = 0;
virtual double volume() = 0;
};
class ThreeDRectangle : public ThreeDShape {
public:
std::string text() override { return "3d rectangle"; }
double volume() override { return 2.0; }
};
class ThreeDTriangle : public ThreeDShape {
public:
std::string text() override { return "3d triangle"; }
double volume() override { return 4.0; }
};
class ShapeFactory {
public:
virtual TwoDShape* create2dShape() = 0;
virtual ThreeDShape* create3dShape() = 0;
};
class RectangleFactory : public ShapeFactory {
public:
TwoDShape* create2dShape() override {
return new TwoDRectangle();
}
ThreeDShape* create3dShape() override {
return new ThreeDRectangle();
}
};
class TriangleFactory : public ShapeFactory {
public:
TwoDShape* create2dShape() override {
return new TwoDTriangle();
}
ThreeDShape* create3dShape() override {
return new ThreeDTriangle();
}
};
ShapeFactory* makeShapeFactory(std::string shape) {
if (shape == "triangle") {
return new TriangleFactory();
} else {
return new RectangleFactory();
}
};
int main() {
// Get input from the terminal.
std::string shape;
std::cout << "What shape would you like? ";
std::getline(std::cin, shape);
ShapeFactory* p = makeShapeFactory(shape);
TwoDShape* s2 = p->create2dShape();
ThreeDShape* s3 = p->create3dShape();
std::cout << s2->text() << " and " << s3->text() << std::endl;
delete p;
delete s2;
delete s3;
return 0;
}
As stated before, an Abstract Factory is implemented in terms of Factory Methods. That is why people confuse them. However, it is their concerns that differentiate them. When applying patterns, always consider their concerns first, and then their implementation.
1 See what's the advantage of using factory method pattern over simple factory?