Simple Factory Limitations
Basic factory implementations often suffer from inflexibility when new types need to be added. Consider a web crawler system with different spider types:
enum class CrawlerType {
TEXT,
IMAGE,
};
class BasicSpiderFactory {
public:
static shared_ptr<Spider> CreateCrawler(CrawlerType type) {
switch(type) {
case CrawlerType::TEXT: return make_shared<TextCrawler>();
case CrawlerType::IMAGE: return make_shared<ImageCrawler>();
}
}
};
This aproach requires modifying the factory code whenever new crawler types are introduced, violating the open/closed principle.
Factory Method Solution
The factory method pattern solves this by delegating object creation to subclasses:
class WebCrawler {
public:
virtual void FetchContent() = 0;
};
class CrawlerFactory {
public:
virtual shared_ptr<WebCrawler> CreateCrawler() = 0;
};
New crawler types can be added without modifying existing code:
class VideoCrawler : public WebCrawler {
void FetchContent() override { /* video fetching logic */ }
};
class VideoCrawlerFactory : public CrawlerFactory {
shared_ptr<WebCrawler> CreateCrawler() override {
return make_shared<VideoCrawler>();
}
};
Complete Implementation
// WebCrawler.h
#pragma once
#include <memory>
class WebCrawler {
public:
virtual void FetchContent() = 0;
};
class CrawlerFactory {
public:
virtual shared_ptr<WebCrawler> CreateCrawler() = 0;
};
// VideoCrawler.h
#pragma once
#include "WebCrawler.h"
class VideoCrawler : public WebCrawler {
public:
void FetchContent() override {
// Video fetching implementation
}
};
class VideoCrawlerFactory : public CrawlerFactory {
public:
shared_ptr<WebCrawler> CreateCrawler() override {
return make_shared<VideoCrawler>();
}
};
// Usage
int main() {
shared_ptr<CrawlerFactory> factory = make_shared<VideoCrawlerFactory>();
shared_ptr<WebCrawler> crawler = factory->CreateCrawler();
crawler->FetchContent();
}