Implementação do Composite Pattern Utilizando PHP

Overview

Composite Pattern - PHP

Implementação do Composite Pattern Utilizando PHP


Descrição

O Composite Pattern é um padrão de projeto estrutural que permite que você componha objetos em estrutura de árvores e então trabalhe com essas estruturas como se elas fossem objetos individuais. Referência: https://refactoring.guru/pt-br/design-patterns/composite

Caso de Uso

Neste exemplo simulamos o uso do Composite Pattern para calcular o preço dos items de um pedido. Até este ponto é algo bem comum e poderíamos resolver simplesmente usar uma estrutura de repetição e armazenar a soma do valor de cada item em uma variável auxiliar e retornar seu valor.

Mas para este exemplo, o pedido é composto por itens e este itens podem ser produtos ou caixas que contém produtos. Imagens de produtos

Ao mentalizarmos este requisito, começamos a pensar em como diferenciar os objetos Produtos dos objetos Caixas. Sim, isto seria uma saída, mas e se tivéssemos 3, 4, 5, n.. objetos direferentes isto se tornaria em um verdadeiro quebra-cabeça.

Por este motivo temos Composite Pattern. Com o Composite Pattern podemos executar um método que é comum a todos os elementos da estrutura sem nos preocupar em saber o tipo do objeto que está sendo iterado é um produto ou uma caixa com produtos.

Agora vamos ao exemplo!

Estrutura Composite Pattern

A estrutura do Composite Pattern tem os seguintes elementos: Component, Leaf, Composite e Client.

Agora vamos entender cada um desse componentes e realizar as associações com o nosso caso de uso:

Component

O Component é uma interface que define as operações que são comuns para os elementos simples(Leaf) ou complexos(Composite), ela é a nossa árvore na estrutura. Em nosso caso de uso, o Component é o item do pedido. O item do pedido é composto por produtos(elementos simples) ou caixas(elementos complexos).

Leaf

A Leaf ou folha representa o componente simples da árvore. Realizando a associação com o nosso caso de uso, o leaf será representado pelo objeto Produto.

Composite

O Composite ou Container é o elemento complexo da arvore, o Composite pode conter elementos simples ou compostos. Em nosso caso de uso é a Caixa, ela pode conter os produtos(elementos simples) ou conter caixas(elementos compostos) com outras caixa ou produtos dentro delas.

Client

O Client é o elemento que irá trabalhar com os elementos(Component) sem se importar se é um elemento simples ou composto. Para o Client os elementos são indiferentes. Por utilizar a interface Component para interagir com os elementos, ele não sabe se é uma Leaf ou um Composite. Em nosso caso de uso o Client é representado pelo objeto Pedido. O pedido irá interagir apenas com os items(Component) sem se importar se são Produtos(Leaf) ou Caixas(Composite).

Diagrama do Caso de Uso com o Composite Pattern

Agora que sabemos o conceito do Composite Pattern vamos aplicá-lo ao nosso caso de uso.

Codificação

Vamos começar com a interface ItemDoPedido.php.

<?php

/**
 * Representa o Component do Composite Pattern
 * @author Anglesson Araujo
 */
interface ItemDoPedido
{
  public function calcular();
}

Agora vamos codificar a nossa Leaf: Produto.php.

<?php

/**
 * Representa o Leaf(Folha) do Composite Pattern
 * @author Anglesson Araujo
 */
class Produto implements ItemDoPedido
{
    private string $codigo;
    private float $valor;

    public function __construct(string $codigo)
    {
        $this->codigo = $codigo;
    }

    /**
     * Método responsável por retornar o valor do produto.
     * @return float Valor do Produto
     */
    public function calcular()
    {
      return $this->valor;
    }

    /**
    * Método responsável por definir o valor do produto.
    * @param float Preço do Produto
    */
    public function setValor(float $valor)
    {
      $this->valor = $valor;
    }

    /**
     * Método responsável por retornar o valor do produto.
     * @return string Código do produto.
     */
    public function getCodigo()
    {
        return $this->codigo;
    }
}

O nosso Composite é a Caixa. Caixa.php.

<?php

/**
 * Representa o Composite ou Container do Composite Pattern
 * @author Anglesson Araujo
 */
class Caixa implements ItemDoPedido
{
  private $codigo;
  private $items;

  public function __construct($codigo)
  {
      $this->items = [];
      $this->codigo = $codigo;
  }

  /**
   * Método responsável por adicionar items à Caixa.
   * @param ItemDoPedido Objeto do tipo ItemDoPedido
   */
  public function adiciona(ItemDoPedido $item)
  {
    $this->items[] = $item;
  }

  /**
   * Método responsável por remover item da Caixa.
   * @param ItemDoPedido Item do Pedido
   */
  public function remove(ItemDoPedido $item)
  {
    $key = array_search($item, $this->items);
    if($key!==false){
        unset($this->items[$key]);
    }
  }

  /**
   * Método responsável por retornar todos os items da Caixa.
   * @return array Lista de items que compõem a caixa.
   */
  public function getItens()
  {
    return $this->items;
  }

  /**
   * Método responsável por definir o código da caixa.
   * @param string Codigo da caixa
   * @return void
   */
  public function setCodigo(string $codigo)
  {
    $this->codigo = $codigo;
  }

  /**
   * Método responsável retornar o código da caixa.
   * @return string Codigo da caixa
   */
  public function getCodigo()
  {
    return $this->codigo;
  }

  /**
   * Método responsável por delegar a atividade de calculo para os items que compõe a caixa.
   * @return float Soma dos produtos na caixa.
   */
  public function calcular()
  {
    $soma = 0;
    foreach ($this->items as $item)
    {
      $soma = $soma + $item->calcular();
    }
    return $soma;
  }
}

Para concluirmos, vamos codificar o Client Pedido.php.

<?php
/**
 * Representa o Client do Composite Pattern.
 * @author Anglesson Araujo
 */
class Pedido
{
    private $items;
    private string $codigo;

    /**
     * Método contrutor da classe
     * @param string $codigo
     */
    public function __construct(string $codigo)
    {
        $this->codigo = $codigo;
        $this->items = [];
    }

    /**
     * Método responsável por adicionar itens ao pedido.
     * @param ItemDoPedido $item Item do pedido pode ser um Produto ou uma Caixa.
     * @return void
     */
    public function adicionarItem(ItemDoPedido $item)
    {
        $this->items[] = $item;
    }

    /**
     * Método responsável por remover item da Caixa.
     * @param ItemDoPedido Item do Pedido
     */
    public function removerItem(ItemDoPedido $item)
    {
        $key = array_search($item, $this->items);
        if($key!==false){
            unset($this->items[$key]);
        }
    }

    /**
     * Método responsável por retornar a soma de todos os items,
     * independente se são caixas com produtos ou apenas produtos.
     * @return int|mixed
     */
    public function finalizarPedido()
    {
        $total = 0;
        foreach ($this->items as $item)
        {
            $total = $total + $item->calcular();
        }
        return $total;
    }

    /**
     * Método responsável por retornar o código do produto.
     * @return string
     */
    public function getCodigo()
    {
        return $this->codigo;
    }
}

Vamos testar nossa implemtação com o arquivo index.php

<?php

include_once 'ItemDoPedido.php';
include_once 'Produto.php';
include_once 'Caixa.php';
include_once 'Pedido.php';

// Cria produtos
$produto1 = new Produto('001');
$produto1->setValor(5.00);

$produto2 = new Produto('002');
$produto2->setValor(15.00);

$produto3 = new Produto('003');
$produto3->setValor(50);

$produto4 = new Produto('004');
$produto4->setValor(234.00);

// Cria Caixa Filha
$caixaFilha = new Caixa('CXFILHA001');
$caixaFilha->adiciona($produto3);
$caixaFilha->adiciona($produto4);

// Cria Caixa Mãe
$caixa = new Caixa('CXMAE001');
$caixa->adiciona($produto1);
$caixa->adiciona($produto2);
$caixa->adiciona($caixaFilha);

// Classe Pedido representa a classe cliente.
$pedido = new Pedido('PED123');
$pedido->adicionarItem($caixa);

echo "O valor do PEDIDO - {$pedido->getCodigo()} é R$ ".$pedido->finalizarPedido()."\n";

Como vocês podem ver toda a 'mágica' acontece na função finalizarPedido() da classe Pedido.php. Nela realizamos a iteração sem nos preocupar em verificar se são caixas ou apenas produtos. Além disso, também não nos preocupamos em saber quantos os níveis de caixas que estão compondo-as.

Espero ter ajudado!# composite-pattern-php

You might also like...
this starter kite inspired by laravel & Geo and mvc pattern. it's wrap for Wordpress built in classes.

WordpressStarterKite Introduction Built With Prerequisite Directory Structure Guidelines Getting Started Authors Introduction this starter kite inspir

Pattern Lab Standard Edition for Twig

Pattern Lab Standard Edition for Twig The Standard Edition for Twig gives developers and designers a clean and stable base from which to develop a Twi

Glob-like file and pattern matching utility.

Glob-like file and pattern matching utility.

The Current US Version of PHP-Nuke Evolution Xtreme v3.0.1b-beta often known as Nuke-Evolution Xtreme. This is a hardened version of PHP-Nuke and is secure and safe. We are currently porting Xtreme over to PHP 8.0.3
The Current US Version of PHP-Nuke Evolution Xtreme v3.0.1b-beta often known as Nuke-Evolution Xtreme. This is a hardened version of PHP-Nuke and is secure and safe. We are currently porting Xtreme over to PHP 8.0.3

2021 Nightly Builds Repository PHP-Nuke Evolution Xtreme Developers TheGhost - Ernest Allen Buffington (Lead Developer) SeaBeast08 - Sebastian Scott B

A sampling profiler for PHP written in PHP, which reads information about running PHP VM from outside of the process.

Reli Reli is a sampling profiler (or a VM state inspector) written in PHP. It can read information about running PHP script from outside of the proces

PHP Meminfo is a PHP extension that gives you insights on the PHP memory content

MEMINFO PHP Meminfo is a PHP extension that gives you insights on the PHP memory content. Its main goal is to help you understand memory leaks: by loo

A sampling profiler for PHP written in PHP, which reads information about running PHP VM from outside of the process.

Reli Reli is a sampling profiler (or a VM state inspector) written in PHP. It can read information about running PHP script from outside of the proces

A multithreaded application server for PHP, written in PHP.

appserver.io, a PHP application server This is the main repository for the appserver.io project. What is appserver.io appserver.io is a multithreaded

Easy to use utility functions for everyday PHP projects. This is a port of the Lodash JS library to PHP

Lodash-PHP Lodash-PHP is a port of the Lodash JS library to PHP. It is a set of easy to use utility functions for everyday PHP projects. Lodash-PHP tr

Owner
Anglesson Araújo
Anglesson is systems analyst at the Rede Damas Educacional, where he give support and trainning peoples for use TOTVS RM. In addition, develops softwares web.
Anglesson Araújo
Formulário de contato utilizando HTML, CSS, Bootstrap, PHP, Javascript e conexão ao banco de dados MySQL.

Formulário de Contato Tecnologias | Projeto | Licença | ?? Tecnologias Esse projeto foi desenvolvido com as seguintes tecnologias: HTML CSS PHP JavaSc

Douglas Duarte 3 Feb 10, 2022
Meu projeto de final do curso, utilizando laravel.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

null 1 Nov 28, 2021
Este Repositório guarda arquivos dos meus primeiros passos utilizando o Framework Laravel. Curso: Matheus Battisti.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

null 1 Jun 12, 2022
This is a Native PHP MVC. If you will build your own PHP project in MVC with router, you can clone this ready to use MVC pattern repo.

Welcome to PHP-Native-MVC-Pattern ?? If you will build your own PHP project in MVC with router, you can clone this ready to use MVC pattern repo. Work

null 2 Jun 6, 2022
YL MVC Structure (PHP MVC) is a pattern made in PHP used to implement user interfaces, data, and controlling logic.

YL MVC Structure (PHP MVC) is a pattern made in PHP used to implement user interfaces, data, and controlling logic. It is built based on the combination of ideas from the Yii framework and Laravel framework (yl).

Tan Nguyen 3 Jan 3, 2023
PHP implementation of circuit breaker pattern.

What is php-circuit-breaker A component helping you gracefully handle outages and timeouts of external services (usually remote, 3rd party services).

ArturEjsmont 169 Jul 28, 2022
PHP regexp pattern matching Unicode emojis

Emoji pattern This package provides regexp patterns to match Unicode emojis. All forms of emojis are matched, including: Single-character emoji ( ?? )

Incenteev 7 Nov 5, 2022
Easy Repository pattern for PHP Phalcon framework.

Phalcon Repositories Introduction Phalcon Repositories lets you easily build repositories for your Phalcon models, for both SQL and Mongo drivers. PHP

Michele Angioni 18 Oct 7, 2022
Design Pattern Examples in PHP

Design Patterns in PHP This repository is part of the Refactoring.Guru project. It contains PHP examples for all classic GoF design patterns. Each pat

Refactoring.Guru 909 Dec 22, 2022
Simple repository pattern for laravel, with services!

With repository and service you can separate business logic and query logic, slim controller and DRY. Simple generate repository and service with artisan command, automatically bind interface with repository

Yaz3 27 Jan 1, 2023