Design - Sottoclassi con implementazioni simili

-1

Cercherò di dare una parola il più sinteticamente possibile.

Al momento ho un oggetto chiamato StoresAdaptor che eredita da una classe base ERPAdaptor , che accetta un oggetto Stores e lo inserisce in un sistema ERP di terze parti tramite un modello di progettazione dell'adattatore.

Ora, ci sono più tipi di questi movimenti Stores . Ognuno ha la propria implementazione, ma la creazione è quasi identica. Il problema deriva dal fatto che questo oggetto Stores ha la posizione "A" e l'oggetto Line ha la posizione "Da", tuttavia, quando si effettua una Movement , è necessario conoscere entrambi i "A" e "Da".

public class StoresAdaptor : ERPAdaptor
{
    protected Stores storesRequest
    {
        get { return (Stores) this.GenericObject; }
    }
    public StoresAdaptor(Data_Controller DCO, GenericObject storesRequest, ERPConnection conn)
        : base(DCO, storesRequest, conn)
    { }
    private class ReturnMiscMaterialAdaptor
    {
        //This here feels wrong...
        private StoresAdaptor _storesAdaptor;
        private Stores.Line _storesLine;

        public ReturnMiscMaterialAdaptor(StoresAdaptor storesAdaptorRef, Stores.Line storesLine)
        {
            _storesAdaptor= storesAdaptorRef;
            _storesLine= storesLine;
        }
     // task to bay
        public Update()
        {
            ERPSystem.ToLocation = _storesAdaptor.storesRequest.ToLocation;
            ERPSystem.FromLocation = _storesLine.FromLocation;
            //Return specific functionality
        }
    }
    private class IssueMiscMaterialAdaptor
    {
        //As well as here... there has to be a better way to do this...
        private StoresAdaptor _storesAdaptor;
        private Stores.Line _storesLine;

        public IssueMiscMaterialAdaptor(StoresAdaptor storesAdaptorRef, Stores.Line storesLine)
        {
            _storesAdaptor= storesAdaptorRef;
            _storesLine= storesLine;
        }
        public Update()
        {
            ERPSystem.ToLocation = _storesAdaptor.storesRequest.ToLocation;
            ERPSystem.FromLocation = _storesLine.FromLocation;
            //Issue specific functionality
        }
        // bay to task
    }

In sostanza, abbiamo bisogno di mantenere l'oggetto header ( Stores ) esposto a tutte le sottoclassi, mentre si passa in riga ( Line ) alle sottoclassi separate per essere opportunamente attivate.

Quello che ho fatto finora è passato in un riferimento all'oggetto nel costruttore della sottoclasse, ma trovo che sto ripetendo esattamente gli stessi campi e la stessa dichiarazione del ctor (cambiando il nome in modo che corrisponda ovviamente) che dopo la terza volta che ho battuto "Paste" mi ha fatto fermare e fare un passo indietro e rendermi conto che sto facendo qualcosa di sbagliato.

Ho anche pensato di creare questi 'sub-classes' : StoresAdaptor ma la base StoresAdaptor eredita da una classe astratta senza alcun costruttore senza parametri e, in quanto tale, dovrei duplicare il costruttore della classe base più e più volte.

Qualcuno può suggerire quale modello funzionerebbe meglio in questo scenario? Continuerò a lavorarci ma se sento che qualcosa non funziona, ci deve essere qualcosa di MOLTO sbagliato nel design.

    
posta DeeKayy90 09.01.2017 - 09:49
fonte

2 risposte

1

ReturnMiscMaterialAdaptor e IssueMiscMaterialAdaptor sembrano essere classi interne. È giusto? Invece, rendi queste sottoclassi a abstract class StoresAdaptor . Le classi abstract consentono l'implementazione ereditata, inclusi i costruttori. Uno o entrambi di ERPAdaptor e StoresAdaptor potrebbero essere abstract - Non so abbastanza del design per essere più specifico.

Considerato quanto sopra non dovrebbe essere necessario passare il parametro Stores.Lines

Stores.Line sembra essere un componente all'interno di Stores quindi in Stores wrap che:

class Stores {
   public string FromLocation { get { return this.Line.FromLocation; }} 
}

In alternativa, ma non è preferibile, è possibile includere le proprietà Store nella classe dell'adattatore. Nota, questo è probabilmente discutibile se si utilizza l'ereditarietà, come suggerito.

prima

public Update()
    {
        ERPSystem.ToLocation = _storesAdaptor.storesRequest.ToLocation;
        ERPSystem.FromLocation = _storesLine.FromLocation;
        //Return specific functionality
    }

DOPO:

public ReturnMiscMaterialAdaptor(StoresAdaptor storesAdaptorRef, Stores.Line storesLine)
    {
        _storesAdaptor= storesAdaptorRef;
        _storesLine= storesLine;
        this.ToLocation = _storesAdaptor.storesRequest.ToLocation;
        this.FromLocation = _storesLine.FromLocation;
    }    
public Update()
    {
        ERPSystem.ToLocation = this.ToLocation;
        ERPSystem.FromLocation = this.FromLocation;
        //Return specific functionality
    }

In generale, sto dicendo di applicare il principio di conoscenza minimo nelle classi adaptee e adapter.

Non sono d'accordo con la nozione affermata in un'altra risposta che le classi dell'adattatore potrebbero essere statiche. Come puoi esporre un'API per un oggetto stateful e garantirne la coerenza? Cosa succede quando il cliente ha bisogno di un secondo oggetto adattato?

P.S. l'adattatore è errato, dovrebbe essere l'adattatore.

    
risposta data 09.01.2017 - 16:55
fonte
1

Penso che il problema si risolva facilmente una volta che ti rendi conto che non è necessario un StoresAdaptor e un Stores.Line per costruire un ReturnMiscMaterialAdaptor o un IssueMiscMaterialAdaptor , né la classe ha bisogno di tenerli nel stato interno per funzionare. Basati sul codice, non sembrano necessari finché non viene chiamato il metodo Update , quindi dovrebbero essere i parametri di quella chiamata.

In effetti, sembra quasi che le classi Adaptor siano buoni candidati per le classi static - ovviamente non attualmente possibile perché sono sottoclassi di ERPAdaptor .

Una possibile soluzione alternativa:

private class IssueMiscMaterialAdaptor
{
    public IssueMiscMaterialAdaptor() { }

    public Update(StoresAdaptor storesAdaptorRef, Stores.Line storesLine)
    {
        var _storesAdaptor= storesAdaptorRef;
        var _storesLine= storesLine;
        ERPSystem.ToLocation = _storesAdaptor.storesRequest.ToLocation;
        ERPSystem.FromLocation = _storesLine.FromLocation;
        //Issue specific functionality
    }
    // bay to task
}

o anche

private class IssueMiscMaterialAdaptor
{
    public IssueMiscMaterialAdaptor() { }

    public Update(Location toLocation, Location fromLocation)
    {
        ERPSystem.ToLocation = toLocation;
        ERPSystem.FromLocation = fromLocation;
        //Issue specific functionality
    }
    // bay to task
}
    
risposta data 09.01.2017 - 15:10
fonte

Leggi altre domande sui tag