Purpose
The purpose of the design pattern
Decouple an abstraction from its implementation so that the two can vary independently.
UML
UML design pattern diagram
Code
Code snippets
Formatter
Formatter Interface
namespace DesignPatterns\Structural\Bridge;
interface Formatter
{
public function format(string $text): string;
}
Service
The purpose of this Service class is to eliminate boilerplate code over the concrete service classes (HelloWorldService and PingService - which extend it). A class which implements the Formatter Interface is passed into its construct which adjusts the behaviour of the service.
namespace DesignPatterns\Structural\Bridge;
abstract class Service
{
public function __construct(protected Formatter $implementation)
{
}
final public function setImplementation(Formatter $printer)
{
$this->implementation = $printer;
}
abstract public function get(): string;
}
HelloWorldService
The HelloWorldService extends the abstract class Service.
namespace DesignPatterns\Structural\Bridge;
class HelloWorldService extends Service
{
public function get(): string
{
return $this->implementation->format('Hello World');
}
}
PingService
The PingService class extends the abstract class Service.
namespace DesignPatterns\Structural\Bridge;
class PingService extends Service
{
public function get(): string
{
return $this->implementation->format('pong');
}
}
PlainTextFormatter
Adjusts the service output via formatting with plain text.
namespace DesignPatterns\Structural\Bridge;
class PlainTextFormatter implements Formatter
{
public function format(string $text): string
{
return $text;
}
}
HtmlFormatter
Adjusts the service output via formatting with HTML.
namespace DesignPatterns\Structural\Bridge;
class HtmlFormatter implements Formatter
{
public function format(string $text): string
{
return sprintf('%s
', $text);
}
}
Tests
When a service is instantiated, a formatter is passed into its construct which adjusts the behaviour.
i.e - Output Hello World in Plain Text and Output Hello World wrapped in HTML tags.
public function testCanPrintUsingThePlainTextFormatter()
{
$service = new HelloWorldService(new PlainTextFormatter());
$this->assertSame('Hello World', $service->get());
}
public function testCanPrintUsingTheHtmlFormatter()
{
$service = new HelloWorldService(new HtmlFormatter());
$this->assertSame('Hello World
', $service->get());
}