samedi 18 août 2018

Which of these patterns is better OOP design when I have separate "data" and "procedures"?

Let's say for example that this is my data

public interface IPerson
{
    string Name { get; }

    int Age { get; }
}

public class AmericanCitizen : IPerson
{
    public string Name { get; set; }

    public int Age { get; set; }

    public SocialSecurityNumber SSN { get; set; }
}

public class StackOverflowPoster : IPerson
{
    public string Name { get; set; }

    public int Age { get; set; }

    public string Alias { get; set; }   
}

meaning these are just "value bags" (like models of database rows).

And let's say I need some type of procedure that acts on different implementations.

One way is to have a method with switch or if-else, like

public class UniqueIdentifierPrinter : IUniqueIdentifierPrinter
{   
    public void Identity(IPerson person)
    {
        if (person is AmericanCitizen)
        {
            AmericanCitizen american = (AmericanCitizen)person;
            Console.WriteLine(american.SSN.ToString());
        }
        else if (person is StackOverflowPoster)
        {
            StackOverflowPoster SOer = (StackOverflowPoster)person;
            Console.WriteLine(SOer.Alias);
        }
        else
        {
            throw new NotSupportedException();
        }
    }
}

Another way I can think of is to put the Identify implementations in separate classes, like

public interface IPersonIdentifier<out T> where T : IPerson
{
    void Identify();    
}

public class AmericanCitizenIdentifer : IPersonIdentifier<AmericanCitizen>
{
    AmericanCitizen american;

    public AmericanCitizenIdentifer(AmericanCitizen american)
    {
        this.american = american;
    }

    public void Identify()
    {
        Console.WriteLine(american.SSN.ToString());
    }
}


public class StackOverflowPosterIdentifier : IPersonIdentifier<StackOverflowPoster>
{
    StackOverflowPoster poster;

    public StackOverflowPosterIdentifier(StackOverflowPoster american)
    {
        this.poster = poster;
    }

    public void Identify()
    {
        Console.WriteLine(poster.Alias);
    }
}


public static class Identifying
{
    public static void Identify(IPerson person)
    {
        IPersonIdentifier<IPerson> identifier;

        if (person is AmericanCitizen)
        {
            identifier = new AmericanCitizenIdentifer((AmericanCitizen)person);
        }
        else if (person is StackOverflowPoster)
        {
            identifier = new StackOverflowPosterIdentifier((StackOverflowPoster)person);
        }
        else
        {
            throw new NotSupportedException();
        }

        identifier.Identify();
    }
}

So which is better, and why?

Aucun commentaire:

Enregistrer un commentaire