<?php
interface ExternalApi
{
public function sendByEmail();
public function sendByFax();
public function sendBySMS();
// more sending modes ...
}
class Api1 implements ExternalApi
{
public function sendByEmail()
{
echo __CLASS__." sending email<br>\n";
}
public function sendByFax()
{
echo __CLASS__." sending fax<br>\n";
}
public function sendBySMS()
{
echo __CLASS__." sending SMS<br>\n";
}
}
class Customer
{
public const EMAIL = 'email';
public const FAX = 'fax';
public const SMS = 'sms';
public const EMAIL_AND_FAX = 'email_and_fax';
public const PHONE = 'phone';
public const PLANE = 'plane';
public const BOAT = 'boat';
public const SATELITE = 'satelite';
public const CAB = 'cab';
// more contact types...
public ?string $contactType;
}
class Invoice
{
public Customer $customer;
public function __construct(Customer $customer)
{
$this->customer = $customer;
}
}
class InvoiceSender
{
private ExternalApi $api;
public function __construct(ExternalApi $api)
{
$this->api = $api;
}
public function send(Invoice $invoice)
{
switch($invoice->customer->contactType) {
case Customer::EMAIL :
$this->api->sendByEmail();
break;
case Customer::FAX :
$this->api->sendByFax();
break;
case Customer::SMS :
$this->api->sendBySMS();
break;
case Customer::EMAIL_AND_FAX:
$this->api->sendByEmail();
$this->api->sendByFax();
break;
// more cases ...
}
}
}
$customer = new Customer();
$customer->contactType = Customer::EMAIL_AND_FAX;
$invoice = new Invoice($customer);
$api = new Api1();
$invoiceSender = new InvoiceSender($api);
$invoiceSender->send($invoice);
As you can see the switch statement of InvoiceSender::send is increased each time I add a new "contact type".
Do you know which design pattern could solve this problem ?
Create an interface like SendInvoiceInterface
with a send
and a shouldSend
method. Then create 3 implementations:
EmailInvoiceSender
FaxInvoiceSender
SMSInvoiceSender
Next inject these all into your InvoiceSender
as an array. Then instead of the switch-case you can loop over all the senders and 'ask' them if they shouldSend
. If that evaluates to true you can call send
on them.
This way the logic stays inside each sender itself instead of the growing switch-case.