There are so many Symfony components already, and they have some pretty neat perks. But have you seen them in action?
Design patterns are not a silver bullet. They will never resolve your problem on their own. On the other hand, design patterns provide a common ground for developers without going into details and could be used as building bricks to solve some more advanced problems.
During my presentation, I will take a closer look and explain the appliance of selected design patterns. What is more, I will take advantage of the Symfony ecosystem to implement them with ease.
I will do the presentation on sample code that developers will understand at all levels of expertise.
50. final class CompositeOrderProcessor implements OrderProcessor
{
public function processOrder(Cart $cart): void
{
// Apply promotion
$this->applyPromotion($cart);
// Apply taxation
$this->applyTaxation($cart);
}
private function applyTaxation(Cart $cart): void
{
/** @var CartItem $item */
foreach ($cart->getItems() as $item) {
if ('shirt' === $item->getType()) {
$item->setTaxationPercentage(0.23);
}
if ('book' === $item->getType()) {
$item->setTaxationPercentage(0.08);
}
}
}
private function applyPromotion(Cart $cart): void
{
if ($cart->getPrice() >= 1000) {
$cart->applyPercentageDiscount(0.1);
}
}
}
51. final class CompositeOrderProcessor implements OrderProcessor
{
public function processOrder(Cart $cart): void
{
// Apply promotion
$this->applyPromotion($cart);
// Apply taxation
$this->applyTaxation($cart);
}
private function applyTaxation(Cart $cart): void
{
/** @var CartItem $item */
foreach ($cart->getItems() as $item) {
if ('shirt' === $item->getType()) {
$item->setTaxationPercentage(0.23);
}
if ('book' === $item->getType()) {
$item->setTaxationPercentage(0.08);
}
}
}
private function applyPromotion(Cart $cart): void
{
if ($cart->getPrice() >= 1000) {
$cart->applyPercentageDiscount(0.1);
}
}
}
52. final class OrderTaxationProcessor implements OrderProcessor
{
public function processOrder(Cart $cart): void
{
/** @var CartItem $item */
foreach ($cart->getItems() as $item) {
if ('shirt' === $item->getType()) {
$item->setTaxationPercentage(0.23);
}
if ('book' === $item->getType()) {
$item->setTaxationPercentage(0.08);
}
}
}
}
53. final class CompositeOrderProcessor implements OrderProcessor
{
public function processOrder(Cart $cart): void
{
// Apply promotion
$this->applyPromotion($cart);
// Apply taxation
$this->applyTaxation($cart);
}
private function applyPromotion(Cart $cart): void
{
if ($cart->getPrice() >= 1000) {
$cart->applyPercentageDiscount(0.1);
}
}
}
54. final class OrderPromotionProcessor implements OrderProcessor
{
public function processOrder(Cart $cart): void
{
if ($cart->getPrice() >= 1000) {
$cart->applyPercentageDiscount(0.1);
}
}
}
55. final class CompositeOrderProcessor implements OrderProcessor
{
private OrderPromotionProcessor $orderPromotionProcessor;
private OrderTaxationProcessor $orderTaxationProcessor;
public function __construct(
OrderPromotionProcessor $orderPromotionProcessor,
OrderTaxationProcessor $orderTaxationProcessor
) {
$this->orderPromotionProcessor = $orderPromotionProcessor;
$this->orderTaxationProcessor = $orderTaxationProcessor;
}
public function processOrder(Cart $cart): void
{
// Apply promotion
$this->orderPromotionProcessor->processOrder($cart);
// Apply taxation
$this->orderTaxationProcessor->processOrder($cart);
}
}
58. final class CompositeOrderProcessor implements OrderProcessor
{
private OrderPromotionProcessor $orderPromotionProcessor;
private OrderTaxationProcessor $orderTaxationProcessor;
public function __construct(
OrderPromotionProcessor $orderPromotionProcessor,
OrderTaxationProcessor $orderTaxationProcessor
) {
$this->orderPromotionProcessor = $orderPromotionProcessor;
$this->orderTaxationProcessor = $orderTaxationProcessor;
}
public function processOrder(Cart $cart): void
{
// Apply promotion
$this->orderPromotionProcessor->processOrder($cart);
// Apply taxation
$this->orderTaxationProcessor->processOrder($cart);
}
}
59. final class CompositeOrderProcessor implements OrderProcessor
{
private iterable $orderProcessors;
public function __construct(
OrderPromotionProcessor $orderPromotionProcessor,
OrderTaxationProcessor $orderTaxationProcessor
) {
$this->orderProcessors = [
$orderPromotionProcessor,
$orderTaxationProcessor
];
}
public function processOrder(Cart $cart): void
{
foreach ($this->orderProcessors as $orderProcessor) {
$orderProcessor->processOrder($cart);
}
}
}
60. final class CompositeOrderProcessor implements OrderProcessor
{
private iterable $orderProcessors;
public function __construct(
OrderPromotionProcessor $orderPromotionProcessor,
OrderTaxationProcessor $orderTaxationProcessor
) {
$this->orderProcessors = [
$orderPromotionProcessor,
$orderTaxationProcessor
];
}
public function processOrder(Cart $cart): void
{
foreach ($this->orderProcessors as $orderProcessor) {
$orderProcessor->processOrder($cart);
}
}
}
61. final class CompositeOrderProcessor implements OrderProcessor
{
private iterable $orderProcessors;
public function __construct(
OrderPromotionProcessor $orderPromotionProcessor,
OrderTaxationProcessor $orderTaxationProcessor
) {
$this->orderProcessors = [
$orderPromotionProcessor,
$orderTaxationProcessor
];
}
public function processOrder(Cart $cart): void
{
foreach ($this->orderProcessors as $orderProcessor) {
$orderProcessor->processOrder($cart);
}
}
}
62. final class CompositeOrderProcessor implements OrderProcessor
{
private iterable $orderProcessors;
public function __construct(
OrderPromotionProcessor $orderPromotionProcessor,
OrderTaxationProcessor $orderTaxationProcessor
) {
$this->orderProcessors = [
$orderPromotionProcessor,
$orderTaxationProcessor
];
}
public function processOrder(Cart $cart): void
{
foreach ($this->orderProcessors as $orderProcessor) {
$orderProcessor->processOrder($cart);
}
}
}
63. final class CompositeOrderProcessor implements OrderProcessor
{
private iterable $orderProcessors;
public function __construct(iterable $orderProcessors)
{
$this->orderProcessors = $orderProcessors;
}
public function processOrder(Cart $cart): void
{
foreach ($this->orderProcessors as $orderProcessor) {
$orderProcessor->processOrder($cart);
}
}
}
64. final class CompositeOrderProcessor implements OrderProcessor
{
private iterable $orderProcessors;
public function __construct(iterable $orderProcessors)
{
$this->orderProcessors = $orderProcessors;
}
public function processOrder(Cart $cart): void
{
foreach ($this->orderProcessors as $orderProcessor) {
$orderProcessor->processOrder($cart);
}
}
}
74. final class OrderTaxationProcessor implements OrderProcessor
{
public function processOrder(Cart $cart): void
{
/** @var CartItem $item */
foreach ($cart->getItems() as $item) {
if ('shirt' === $item->getType()) {
$item->setTaxationPercentage(0.23);
}
if ('book' === $item->getType()) {
$item->setTaxationPercentage(0.08);
}
}
}
}
75. final class OrderTaxationProcessor implements OrderProcessor
{
public function processOrder(Cart $cart): void
{
/** @var CartItem $item */
foreach ($cart->getItems() as $item) {
if ('shirt' === $item->getType()) {
$item->setTaxationPercentage(0.23);
}
if ('book' === $item->getType()) {
$item->setTaxationPercentage(0.08);
}
}
}
}
76. final class OrderTaxationProcessor implements OrderProcessor
{
private TaxationStrategyDelegator $taxationStrategy;
public function __construct(TaxationStrategyDelegator $taxationStrategy)
{
$this->taxationStrategy = $taxationStrategy;
}
public function processOrder(Cart $cart): void
{
/** @var CartItem $item */
foreach ($cart->getItems() as $item) {
$this->taxationStrategy->processTaxation($item);
}
}
}
77. final class OrderTaxationProcessor implements OrderProcessor
{
private TaxationStrategyDelegator $taxationStrategy;
public function __construct(TaxationStrategyDelegator $taxationStrategy)
{
$this->taxationStrategy = $taxationStrategy;
}
public function processOrder(Cart $cart): void
{
/** @var CartItem $item */
foreach ($cart->getItems() as $item) {
$this->taxationStrategy->processTaxation($item);
}
}
}
78. final class TaxationStrategyDelegator implements TaxationStrategy
{
public function processTaxation(CartItem $item): void
{
if ('shirt' === $item->getType()) {
$item->setTaxationPercentage(0.23);
}
if ('book' === $item->getType()) {
$item->setTaxationPercentage(0.08);
}
}
}
79. final class TaxationStrategyDelegator implements TaxationStrategy
{
public function processTaxation(CartItem $item): void
{
if ('shirt' === $item->getType()) {
$item->setTaxationPercentage(0.23);
}
if ('book' === $item->getType()) {
$item->setTaxationPercentage(0.08);
}
}
}
80. final class TaxationStrategyDelegator implements TaxationStrategy
{
private ShirtTaxationStrategy $shirtTaxationStrategy;
private BookTaxationStrategy $bookTaxationStrategy;
public function __construct(
ShirtTaxationStrategy $shirtTaxationStrategy,
BookTaxationStrategy $bookTaxationStrategy
) {
$this->shirtTaxationStrategy = $shirtTaxationStrategy;
$this->bookTaxationStrategy = $bookTaxationStrategy;
}
public function processTaxation(CartItem $item): void
{
if ('shirt' === $item->getType()) {
$this->shirtTaxationStrategy->processTaxation($item);
}
if ('book' === $item->getType()) {
$this->bookTaxationStrategy->processTaxation($item);
}
}
}
81. final class TaxationStrategyDelegator implements TaxationStrategy
{
private ShirtTaxationStrategy $shirtTaxationStrategy;
private BookTaxationStrategy $bookTaxationStrategy;
public function __construct(
ShirtTaxationStrategy $shirtTaxationStrategy,
BookTaxationStrategy $bookTaxationStrategy
) {
$this->shirtTaxationStrategy = $shirtTaxationStrategy;
$this->bookTaxationStrategy = $bookTaxationStrategy;
}
public function processTaxation(CartItem $item): void
{
if ('shirt' === $item->getType()) {
$this->shirtTaxationStrategy->processTaxation($item);
}
if ('book' === $item->getType()) {
$this->bookTaxationStrategy->processTaxation($item);
}
}
}
82.
83. final class TaxationStrategyDelegator implements TaxationStrategy
{
private ShirtTaxationStrategy $shirtTaxationStrategy;
private BookTaxationStrategy $bookTaxationStrategy;
public function __construct(
ShirtTaxationStrategy $shirtTaxationStrategy,
BookTaxationStrategy $bookTaxationStrategy
) {
$this->shirtTaxationStrategy = $shirtTaxationStrategy;
$this->bookTaxationStrategy = $bookTaxationStrategy;
}
public function processTaxation(CartItem $item): void
{
if ('shirt' === $item->getType()) {
$this->shirtTaxationStrategy->processTaxation($item);
}
if ('book' === $item->getType()) {
$this->bookTaxationStrategy->processTaxation($item);
}
}
}
84. final class TaxationStrategyDelegator implements TaxationStrategy
{
private ShirtTaxationStrategy $shirtTaxationStrategy;
private BookTaxationStrategy $bookTaxationStrategy;
public function __construct(
ShirtTaxationStrategy $shirtTaxationStrategy,
BookTaxationStrategy $bookTaxationStrategy
) {
$this->shirtTaxationStrategy = $shirtTaxationStrategy;
$this->bookTaxationStrategy = $bookTaxationStrategy;
}
public function processTaxation(CartItem $item): void
{
if ('shirt' === $item->getType()) {
$this->shirtTaxationStrategy->processTaxation($item);
}
if ('book' === $item->getType()) {
$this->bookTaxationStrategy->processTaxation($item);
}
}
}
85. final class TaxationStrategyDelegator implements TaxationStrategy
{
private array $indexedTaxationStrategies;
public function __construct(
ShirtTaxationStrategy $shirtTaxationStrategy,
BookTaxationStrategy $bookTaxationStrategy
) {
$this->indexedTaxationStrategies = [
'shirt' => $shirtTaxationStrategy,
'book' => $bookTaxationStrategy,
];
}
public function processTaxation(CartItem $item): void
{
$this->indexedTaxationStrategies[$item->getType()]->processTaxation($item);
}
}
86. final class TaxationStrategyDelegator implements TaxationStrategy
{
private array $indexedTaxationStrategies;
public function __construct(
ShirtTaxationStrategy $shirtTaxationStrategy,
BookTaxationStrategy $bookTaxationStrategy
) {
$this->indexedTaxationStrategies = [
'shirt' => $shirtTaxationStrategy,
'book' => $bookTaxationStrategy,
];
}
public function processTaxation(CartItem $item): void
{
$this->indexedTaxationStrategies[$item->getType()]->processTaxation($item);
}
}
88. final class TaxationStrategyDelegator implements TaxationStrategy
{
private array $indexedTaxationStrategies;
public function __construct(
ShirtTaxationStrategy $shirtTaxationStrategy,
BookTaxationStrategy $bookTaxationStrategy
) {
$this->indexedTaxationStrategies = [
'shirt' => $shirtTaxationStrategy,
'book' => $bookTaxationStrategy,
];
}
public function processTaxation(CartItem $item): void
{
$this->indexedTaxationStrategies[$item->getType()]->processTaxation($item);
}
}
89. final class TaxationStrategyDelegator implements TaxationStrategy
{
private array $indexedTaxationStrategies;
public function __construct(
ShirtTaxationStrategy $shirtTaxationStrategy,
BookTaxationStrategy $bookTaxationStrategy
) {
$this->indexedTaxationStrategies = [
'shirt' => $shirtTaxationStrategy,
'book' => $bookTaxationStrategy,
];
}
public function processTaxation(CartItem $item): void
{
$this->indexedTaxationStrategies[$item->getType()]->processTaxation($item);
}
}
90. final class TaxationStrategyDelegator implements TaxationStrategy
{
private ServiceLocator $taxationStrategies;
public function __construct(ServiceLocator $taxationStrategies)
{
$this->taxationStrategies = $taxationStrategies;
}
public function processTaxation(CartItem $item): void
{
$this->taxationStrategies->get($item->getType())->processTaxation($item);
}
}
91. final class TaxationStrategyDelegator implements TaxationStrategy
{
private ServiceLocator $taxationStrategies;
public function __construct(ServiceLocator $taxationStrategies)
{
$this->taxationStrategies = $taxationStrategies;
}
public function processTaxation(CartItem $item): void
{
$this->taxationStrategies->get($item->getType())->processTaxation($item);
}
}