Design pattern per la gestione di tre oggetti diversi

1

Sto cercando il modo migliore per risolvere il seguente problema:

I have three lists of different objects: AppleJuice, OrangeJuice & Juice. All Juice properties exists in AppleJuice & OrangeJuice and I only need these from AppleJuice & OrangeJuice. I can´t change the AppleJuice & OrangeJuice implementations since they come from two unrelated SOAP services. My aim is merge these 3 lists in a Juice lists and then remove the duplicates using a concrete match pattern.

Quale modello sarebbe meglio unire questi diversi oggetti?

Stavo pensando di usare il modello di facciata per i diversi oggetti e poi la strategia per il modello di corrispondenza. Se aiuta, userò C # per implementare il codice.

Ecco cosa ho fatto.

In primo luogo, ho esteso la classe Juice e ho creato 3 metodi di estensione per le classi: AppleJuice, OrangeJuice e Juice.

public class JuiceExtended : Juice
{
    public JuiceSourceType JuiceSource { get; set; }
}

public enum JuiceSourceType 
{
    Apple,
    Orange,
    Juice,
    JuiceWithoutSugar
}

Ho bisogno di conoscere la fonte, perché se c'è un duplicato devo mantenere gli oggetti dal Juice

    public static IEnumerable<JuiceExtended> ConvertToExtended(this IEnumerable<AppleJuice> juices)
    {
        var list = juices.Select((x) => {
            var item = new JuiceExtended()
            {
                JuiceSource = JuiceSourceType.Apple,
                //More properties                  
            };
            return item;
        });

        return list;
    }

    public static IEnumerable<JuiceExtended> ConvertToExtended(this IEnumerable<OrangeJuice> juices)
    {
        var list = juices.Select((x) => {
            var item = new JuiceExtended()
            {
                JuiceSource = JuiceSourceType.Orange,
                //More properties
            };
            return item;
        });

        return list;
    }

    public static IEnumerable<JuiceExtended> ConvertToExtended(this IEnumerable<Juice> juices, JuiceSourceType type)
    {
        var list = juices.Select((x) => {
            var item = (JuiceExtended) x;
            item.JuiceSource = type;     
            return item;
        });

        return list;
    }

Dopo questo, ho creato un JuiceHandler e ho implementato il modello di strategia all'interno dell'algoritmo di dedup

public class JuiceHandler : IJuiceHandler
{
    private static IEnumerable<JuiceExtended> _juices;
    private JuiceStrategy _strategy;

    public JuiceHandler()
    {
        _juices = new List<JuiceExtended>();
    }

    public JuiceHandler(JuiceStrategy strategy)
    {
        _juices = new List<JuiceExtended>();
        _strategy = strategy;
    }

    public void Load(IEnumerable<JuiceExtended> juices)
    {
        _juices = _juices.Concat(juices);
    }

    public void SetJuiceStrategy(JuiceStrategy strategy)
    {
        _strategy = strategy;
    }


    public IEnumerable<Juice> Transform()
    {
        if (_strategy == null)
            throw new NullReferenceException("The strategy has not been selected.");

        else if (_juices.Count() == 0)
            return _juices;

        return _strategy.Dedup(_juices);
    }

}

Considerando le risposte sottostanti, @MainMa, penso che sposterò i metodi di estensione nelle classi parziali WCF, perché ho già classi parziali per WCF quindi, non c'è motivo di metterle in un'altra posizione.

    
posta RCalaf 30.05.2016 - 22:13
fonte

2 risposte

1

È possibile utilizzare il pattern di facciata come si pensava di trattare gli oggetti AppleJuice e OrangeJuice come gli oggetti Juice. È piuttosto semplice Ecco la tua classe Juice:

class Juice
{
    Juice(AppleJuice aj)
    {
        this.Color = aj.Color;
        this.VitaminC = aj.VitaminC;
    }

    Juice(OrangeJuice oj)
    {
        this.Color = oj.Color;
        this.VitaminC = oj.VitaminC;
    }

    public ColorType { get; set; }
    public VitaminCType VitaminC { get; set; }
}

Questa classe Juice copre entrambi i tipi di succo ed estrae le informazioni che ti interessano. Per gestire l'uguaglianza Juice, devi implementare IEqualityComparer < Juice >:

class JuiceEq : IEqualityComparer<Juice>
{
    public bool Equals(Juice x, Juice y)
    {
        if (x == null) return y == null;
        if (y == null) return false;
        return x.Color == y.Color && x.VitaminC = y.VitaminC;
    }

    public int GetHashCode(Juice obj)
    {
        if(obj == null) return 0;
        return new { obj.Color, obj.VitaminC }.GetHashCode();
    }
}

Ora, per usarlo quando fai le richieste SOAP e poi rimuovi i duplicati:

IEnumerable<Juice> GetJuice()
{
    IEnumerable<AppleJuice> appleJuices = SoapAppleJuiceRequestRequest();
    IEnumerable<OrangeJuice> orangeJuices = SoapOrangeJuiceRequestRequest();

    IEnumerable<Juice> juices = appleJuices.Select(s => new Juice(s))
      .Concat(orangeJuices.Select(s => new Juice(s));

    IEnumerable<Juice> deDuped = juices.Distinct(new JuiceEq());
    return deDuped;
}
    
risposta data 31.05.2016 - 16:42
fonte
0

Non è necessario alcun motivo specifico qui.

Sebbene non sia possibile modificare le proprietà all'interno delle classi generate dinamicamente create dagli endpoint del servizio SOAP, è possibile aggiungere un comportamento ai tipi, essendo le classi generate parziali.

Ciò rende possibile creare un metodo che converte AppleJuice o OrangeJuice in Juice :

// Make sure the namespace matches with the actual namespace used by the partial class.
namespace ServiceReference1
{
    public partial class AppleJuice
    {
        public Juice ToJuice()
        {
            ...
        }
    }
}

...

public Juice GetAppleJuice()
{
    var client = new AppleServiceClient();
    var appleJuice = client.GetSomeAppleJuice();
    return appleJuice.ToJuice();
}

Da questo momento in poi, puoi lavorare solo con le istanze di Juice (inclusa la memorizzazione nella stessa collezione tipizzata).

Se devi chiamare il servizio e rispedirlo a AppleJuice o OrangeJuice , puoi eseguire la conversione nell'altro modo:

var juice = new Juice(...);
var client = new AppleServiceClient();
var appleJuice = new AppleJuice(juice);
client.DrinkJuice(appleJuice);
    
risposta data 31.05.2016 - 11:08
fonte