Implementação do Padrão Visitor com Adição de Empacotador

O padrão Visitor permite adicionar novas operações a uma hierarquia de classes sem alterá-las. Neste exemplo, estendemos o cenário de carrinho de compras incluindo um novo visitante: o empacotador, responsável por embalar os itens do carrinho.

Diagrama de Classes

O diagrama a seguir ilustra a estrutura do padrão aplicada ao sistema:

Diagrama de classes do padrão VisitorImplementação em Java

Interface Product

public interface Item {
    void accept(Visitor visitor);
}

Classes Concretas de Item

Apple (Maçã)

public class Apple implements Item {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

Book (Livro)

public class Book implements Item {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

Classe Abstrata Visitor

public abstract class Visitor {
    protected String identifier;

    public void setIdentifier(String identifier) {
        this.identifier = identifier;
    }

    public abstract void visit(Apple apple);
    public abstract void visit(Book book);
}

Implementações do Visitor

Customre (Cliente)

public class Customer extends Visitor {
    @Override
    public void visit(Apple apple) {
        System.out.println("Cliente " + identifier + " seleciona maçã");
    }

    @Override
    public void visit(Book book) {
        System.out.println("Cliente " + identifier + " compra livro");
    }
}

Packer (Empacotador)

public class Packer extends Visitor {
    @Override
    public void visit(Apple apple) {
        System.out.println("Empacotador " + identifier + " embala maçã");
    }

    @Override
    public void visit(Book book) {
        System.out.println("Empacotador " + identifier + " embala livro");
    }
}

Saler (Vendedor)

public class Saler extends Visitor {
    @Override
    public void visit(Apple apple) {
        System.out.println("Vendedor " + identifier + " pesa e calcula preço da maçã");
    }

    @Override
    public void visit(Book book) {
        System.out.println("Vendedor " + identifier + " calcula preço do livro");
    }
}

Classe ShoppingCart (Carrinho de Compras)

import java.util.ArrayList;
import java.util.List;

public class ShoppingCart {
    private List<Item> items = new ArrayList<>();

    public void accept(Visitor visitor) {
        for (Item item : items) {
            item.accept(visitor);
        }
    }

    public void addItem(Item item) {
        items.add(item);
    }

    public void removeItem(Item item) {
        items.remove(item);
    }
}

Classe Client (Teste)

public class Client {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        cart.addItem(new Apple());
        cart.addItem(new Book());

        Visitor seller = new Saler();
        seller.setIdentifier("Ana");
        System.out.println("--- Vendedor ---");
        cart.accept(seller);

        Visitor packer = new Packer();
        packer.setIdentifier("Carlos");
        System.out.println("--- Empacotador ---");
        cart.accept(packer);

        Visitor client = new Customer();
        client.setIdentifier("Maria");
        System.out.println("--- Cliente ---");
        cart.accept(client);
    }
}

Implementação em C++

#include <iostream>
#include <string>
#include <list>
using namespace std;

class Item;
class Book;
class Apple;

class Visitor {
protected:
    string name;
public:
    void setName(string n) { name = n; }
    virtual void visit(Apple* apple) {}
    virtual void visit(Book* book) {}
};

class Item {
public:
    virtual void accept(Visitor* visitor) {}
};

class Apple : public Item {
public:
    void accept(Visitor* visitor) override {
        visitor->visit(this);
    }
};

class Book : public Item {
public:
    void accept(Visitor* visitor) override {
        visitor->visit(this);
    }
};

class Customer : public Visitor {
public:
    void visit(Book* book) override {
        cout << "Cliente " << name << " compra livro" << endl;
    }
    void visit(Apple* apple) override {
        cout << "Cliente " << name << " seleciona maçã" << endl;
    }
};

class Saler : public Visitor {
public:
    void visit(Book* book) override {
        cout << "Vendedor " << name << " calcula preço do livro" << endl;
    }
    void visit(Apple* apple) override {
        cout << "Vendedor " << name << " pesa e calcula preço da maçã" << endl;
    }
};

class Packer : public Visitor {
public:
    void visit(Book* book) override {
        cout << "Empacotador " << name << " embala livro" << endl;
    }
    void visit(Apple* apple) override {
        cout << "Empacotador " << name << " embala maçã" << endl;
    }
};

class ShoppingCart {
private:
    list<Item*> items;
public:
    void addItem(Item* item) { items.push_back(item); }
    void removeItem(Item* item) { items.remove(item); }
    void accept(Visitor* visitor) {
        for (auto item : items) {
            item->accept(visitor);
        }
    }
};

int main() {
    ShoppingCart* cart = new ShoppingCart();
    cart->addItem(new Apple());
    cart->addItem(new Book());

    Customer* customer = new Customer();
    customer->setName("João");
    Saler* saler = new Saler();
    saler->setName("Pedro");
    Packer* packer = new Packer();
    packer->setName("Lucas");

    cout << "--- Cliente ---" << endl;
    cart->accept(customer);

    cout << "--- Vendedor ---" << endl;
    cart->accept(saler);

    cout << "--- Empacotador ---" << endl;
    cart->accept(packer);

    return 0;
}

Tags: visitor pattern design patterns java C++ Object-Oriented Programming

Publicado em 7-23 11:42