Padrão de protótipo C#

Resumo : neste tutorial, você aprenderá como usar o padrão C# Prototype para criar novos objetos clonando os existentes.

Introdução ao padrão de protótipo C#

Em C#, as classes são modelos para a criação de novos objetos. Nas classes, você usa o newoperador para criar um objeto.

O padrão Prototype é um padrão de design criacional que permite criar novos objetos clonando objetos existentes. Em outras palavras, o padrão Prototype permite criar novos objetos a partir de objetos existentes, clonando-os sem especificar a classe exata dos objetos.

O padrão Prototype é útil quando você precisa criar novos objetos semelhantes aos existentes, mas com algumas diferenças em seu estado ou comportamento.

O padrão Prototype também é útil para criar um novo objeto complexo e que pode gerar sobrecarga. Portanto, você deseja evitar a complexidade e a sobrecarga clonando um objeto existente em vez de criar um novo do zero.

Para implementar o padrão Prototype, siga estas etapas:

  • Primeiro, defina uma interface ou classe abstrata que especifique um método para clonar objetos.
  • Segundo, crie classes concretas que implementem a interface ou estendam a classe abstrata. Cada classe concreta representa um tipo de objeto específico que pode ser copiado.

Para criar um novo objeto, primeiro chame o Clone()método no objeto protótipo e depois modifique as propriedades do objeto clonado.

O diagrama UML a seguir ilustra como o padrão Prototype funciona.

Padrão de protótipo C#

O padrão Protótipo envolve os seguintes participantes:

  • Protótipo : O protótipo pode ser uma interface ou uma classe abstrata . A interface Prototype (ou classe abstrata) possui o Clone()método que cria um novo objeto a partir de um objeto existente.
  • ConcretePrototype : Esta é uma classe concreta da interface Prototype. A ConcretePrototypeclasse implementa o Clone()método para clonar um objeto.
  • Cliente : Este é o código do cliente que utiliza a interface Prototype para criar novos objetos. O cliente cria um novo objeto clonando um objeto existente e depois personaliza o objeto clonado conforme necessário.

Exemplo de padrão de protótipo C#

O programa C# a seguir demonstra como usar o padrão Prototype criando um protótipo Warrior e clonando-o para criar um novo guerreiro com algumas diferenças em suas propriedades:

using static System.Console;

namespace PrototypePattern;

public interface IPrototype<T>
{
    T Clone();
}

public class Warrior : IPrototype<Warrior>
{
    public string Name  {  get; set;  }
    public int Health {  get; set; }
    public int AttackPower {   get; set;  }

    public Warrior(string name, int health, int attackPower)
    {
        Name = name;
        Health = health;
        AttackPower = attackPower;
    }

    public override string ToString() 
        => $"Name: {Name}, Health:{Health}, AttackPower: {AttackPower}";

    public Warrior Clone() => (Warrior)MemberwiseClone();

}

public class Client
{
    public static void Main(string[] args)
    {
        // Create an instance of the Warrior prototype
        var loki = new Warrior("Loki", 100, 20);

        // Clone the Loki warrior to create
        // a new warrior named Thor
        var thor = loki.Clone();
        thor.Name = "Thor";
        thor.Health = 120;

        // Now we have two different warrior objects with
        // similar properties but with some differences
        WriteLine(loki);
        WriteLine(thor);
    }
}Linguagem de código:  C#  ( cs )

Saída:

Name: Loki, Health:100, AttackPower: 20
Name: Thor, Health:120, AttackPower: 20Linguagem de código:  texto simples  ( texto simples )

Como funciona.

Primeiro, defina uma interface chamada IPrototypecom um parâmetro de tipo genérico T. O Prototype<T>possui um método chamado Clone()que será implementado pelo protótipo concreto para clonagem de um objeto:

public interface IPrototype<T>
{
    T Clone();
}Linguagem de código:  C#  ( cs )

Segundo, defina uma classe concreta Warrior que implemente a IPrototypeinterface. A Warriorclasse tem três propriedades Name,, Healthe AttackPower. Além disso, possui um construtor para inicializar estas propriedades:

public class Warrior : IPrototype<Warrior>
{
    public string Name  {  get; set;  }
    public int Health {  get; set; }
    public int AttackPower {   get; set;  }

    public Warrior(string name, int health, int attackPower)
    {
        Name = name;
        Health = health;
        AttackPower = attackPower;
    }

    public override string ToString() 
        => $"Name: {Name}, Health:{Health}, AttackPower: {AttackPower}";

    public Warrior Clone() => (Warrior)MemberwiseClone();

}Linguagem de código:  C#  ( cs )

A classe Warrior substitui o ToString()método para retornar uma representação de string do objeto warrior.

A classe Warrior também implementa o Clone()método. O Clone()método usa o MemberwiseClone()método que cria uma cópia superficial do Warriorobjeto.

Observe que o  MemberwiseClone método cria uma cópia superficial de um objeto criando um novo objeto e depois copiando os campos não estáticos do objeto para o novo objeto. Se um campo for um tipo de valor, ele executará uma cópia bit a bit do campo. Se um campo for um tipo de referência, ele copiará apenas a referência.

Como as propriedades da Warriorclasse são tipos de valor (exceto the string, que é um tipo de referência, mas um caso especial), a cópia superficial é adequada nesse caso.

Terceiro, defina a Clientclasse com o Main()método como ponto de entrada principal do programa:

public class Client
{
    public static void Main(string[] args)
    {
        // Create an instance of the Warrior prototype
        var loki = new Warrior("Loki", 100, 20);

        // Clone the Loki warrior to create
        // a new warrior named Thor
        var thor = loki.Clone();
        thor.Name = "Thor";
        thor.Health = 120;

        // Now we have two different warrior objects with
        // similar properties but with some differences
        WriteLine(loki);
        WriteLine(thor);
    }
}Linguagem de código:  C#  ( cs )

No Main()método, criamos uma nova instância do Warriorprotótipo com nome Loki, saúde 100e poder de ataque 20. Então clonamos o Lokiguerreiro usando o Clone()método para criar um novo guerreiro chamado Thor.

O Thorguerreiro tem as mesmas propriedades que o Lokiguerreiro, exceto as propriedades Namee Health, que são definidas como Thore 120, respectivamente.

A vantagem de usar o padrão Prototype é que você pode criar novos guerreiros com propriedades semelhantes a um existente sem especificar explicitamente a Warriorclasse. Conseqüentemente, o padrão Prototype oferece flexibilidade e reduz a duplicação de código.

Resumo

  • Use o padrão Prototype para criar um novo objeto clonando um existente sem especificar explicitamente a classe dos objetos.
  • Use o MemberwiseClonemétodo para criar uma cópia superficial do objeto atual.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *