Development Blog
Collection of development articles I've put together...
Abstract Factory Pattern
To create series of related or dependent objects without specifying their concrete classes
0
Likes
Stuart Todd
•
2 years ago
•
Design Patterns: Creational
Purpose
The purpose of the design pattern
To create series of related or dependent objects without specifying their concrete classes. Usually the created classes all implement the same interface. The client of the abstract factory does not care about how these objects are created, it just knows how they go together.
UML
UML design pattern diagram
Code
Code snippets
WriterFactory
A WriterFactory interface which factory classes must implement (and thus adhere to). We’re adding two methods - createCsvWriter and createJsonWriter.
namespace DesignPatterns\Creational\AbstractFactory;
interface WriterFactory
{
public function createCsvWriter(): CsvWriter;
public function createJsonWriter(): JsonWriter;
}
UnixWriterFactory
UnixWriterFactory implements WriterFactory and returns new instances of UnixCsvWriter and UnixJsonWriter depending on which method is called.
namespace DesignPatterns\Creational\AbstractFactory;
class UnixWriterFactory implements WriterFactory
{
public function createCsvWriter(): CsvWriter
{
return new UnixCsvWriter();
}
public function createJsonWriter(): JsonWriter
{
return new UnixJsonWriter();
}
}
WinWriterFactory
WinWriterFactory implements WriterFactory and returns new instances of WinCsvWriter and WinJsonWriter depending on which method is called.
namespace DesignPatterns\Creational\AbstractFactory;
class WinWriterFactory implements WriterFactory
{
public function createCsvWriter(): CsvWriter
{
return new WinCsvWriter();
}
public function createJsonWriter(): JsonWriter
{
return new WinJsonWriter();
}
}
CsvWriter
A CsvWriter interface which concrete classes must implement (and thus adhere to). We’re adding one methods - write.
namespace DesignPatterns\Creational\AbstractFactory;
interface CsvWriter
{
public function write(array $line): string;
}
UnixCsvWriter
UnixCsvWriter overrides the write method and implements CsvWriter interface.
namespace DesignPatterns\Creational\AbstractFactory;
class UnixCsvWriter implements CsvWriter
{
public function write(array $line): string
{
return join(',', $line) . "\n";
}
}
WinCsvWriter
WinCsvWriter overrides the write method and implements CsvWriter interface.
namespace DesignPatterns\Creational\AbstractFactory;
class WinCsvWriter implements CsvWriter
{
public function write(array $line): string
{
return join(',', $line) . "\r\n";
}
}
JsonWriter
A JsonWriter interface which concrete classes must implement (and thus adhere to). We’re adding one methods - write.
namespace DesignPatterns\Creational\AbstractFactory;
interface JsonWriter
{
public function write(array $data, bool $formatted): string;
}
UnixJsonWriter
UnixJsonWriter overrides the write method and implements JsonWriter interface.
namespace DesignPatterns\Creational\AbstractFactory;
class UnixJsonWriter implements JsonWriter
{
public function write(array $data, bool $formatted): string
{
$options = 0;
if ($formatted) {
$options = JSON_PRETTY_PRINT;
}
return json_encode($data, $options);
}
}
WinJsonWriter
WinJsonWriter overrides the write method and implements JsonWriter interface.
namespace DesignPatterns\Creational\AbstractFactory;
class WinJsonWriter implements JsonWriter
{
public function write(array $data, bool $formatted): string
{
return json_encode($data, JSON_PRETTY_PRINT);
}
}
Tests
The factory in action. Our test method below is type hinted to the WriterFactory meaning we can pass in any factory class which implements WriterFactory.
The methods createJsonWriter and createCsvWriter return an instance of JsonWriter and CsvWriter.
The methods createJsonWriter and createCsvWriter return an instance of JsonWriter and CsvWriter.
public function provideFactory()
{
return [
[new UnixWriterFactory()],
[new WinWriterFactory()]
];
}
/**
* @dataProvider provideFactory
*/
public function testCanCreateCsvWriterOnUnix(WriterFactory $writerFactory)
{
$this->assertInstanceOf(JsonWriter::class, $writerFactory->createJsonWriter());
$this->assertInstanceOf(CsvWriter::class, $writerFactory->createCsvWriter());
}