Oggetto con proprietà e metodi personalizzati

5

Un progetto su cui sto lavorando attualmente sui modelli Informazioni sull'ordine. Al momento, c'è una classe con un gruppo di proprietà e funzioni che tutti gli ordini hanno in comune. Inoltre, alcuni dei nostri utenti hanno proprietà e / o funzioni personalizzate in cima all'ordine di base. Alcune di queste proprietà personalizzate sono condivise tra più utenti e alcune sono uniche per un determinato utente. La classe ha circa 50 proprietà diverse, ma un determinato utente potrebbe utilizzare solo 20 di tali proprietà.

Mi piacerebbe riprogettarlo in modo che le proprietà / funzioni di base siano separate dalle proprietà / funzioni personalizzate, ma non so come affrontarlo. Ho pensato di ereditare la classe base, ma un utente potrebbe avere 3 o 4 proprietà personalizzate differenti. Non esiste un'eredità chiara tra le proprietà personalizzate. Ho esaminato lo schema del decoratore, ma l'interfaccia sta cambiando, quindi non sembra adattarsi.

C'è un modo per farlo senza avere la classe monolitica?

Esempi:

Base Properties - OrderID, OrderDate, AccountId, etc.
Customized Properties - BackOrdered, PONumber, ContactPerson
Base Functions - PlaceOrder, CancelOrder
Customized Functions - AddContact, DiscountPriceByPercent

Quindi, alcuni utenti potrebbero avere solo la base, un utente potrebbe avere la base + BackOrdered e un altro utente potrebbe avere base + BackOrdered + PONumber.

Questo problema non è univoco per gli ordini, ho lo stesso problema con altri oggetti nel progetto. Sto cercando un modello / architettura per risolvere il caso generale piuttosto che un modo per gestire gli ordini.

    
posta KevenDenen 16.12.2015 - 00:39
fonte

4 risposte

7

Mi sembra che le proprietà personalizzate riguardino lo stato di elaborazione degli ordini.

Crea un diagramma di stato del processo dell'ordine. Classi di progettazione che spostano il Order da uno stato a un altro, ad esempio da uno stato backordered a uno stato spedito . Il core Order sarebbe contenuto w / in ciascuno in quanto sta attraversando quel particolare cambiamento di stato.

Potrebbe esserci anche una classe che cattura i vari stati in cui un ordine è passato mentre passa da un nuovo ordine, riempito, pagato, spedito, eccetera. Che questa "checklist" sia parte integrante della classe Order è una questione che deve essere risolta dall'analisi del progetto. Potrebbe esserci un OrderProcessor che guida un ordine attraverso il labirinto di stato.

P.S.

La mia risposta sembra abbastanza simile a @ Risposta di Ewan , ad es. "l'ordine può avere cose diverse a loro" Tuttavia, voglio sottolineare gli stati con transizioni tra loro definiti esplicitamente in contrapposizione ai "servizi" discreti senza relazioni definite.

In altre parole per spedire un ordine deve essere in un certo stato (riempito, diciamo) e con design sappiamo che ha attraversato tutti gli stati richiesti fino allo stato corrente. Altrimenti ogni "servizio" non correlato dovrebbe valutare l'ordine per la sua intera catena di stato, inviandolo potenzialmente a "aggiustarlo" - una ciotola di poltiglia potenzialmente ricorsiva.

    
risposta data 20.12.2015 - 17:29
fonte
1

Se tutte le proprietà personalizzate sono conosciute in fase di compilazione, ma possono essere combinate in modi diversi e non si desidera produrre una grande gerarchia di classi, allora tou può usare Pattern misto, la cui implementazione dipenderà dalla programmazione lingua che usi Esempio di codice su Java:

interface Mixed {
    <M, I extends M> void extend(Class<M> iface, I impl);
    <M> M as(Class<M> iface);                
}
class MyObject implements Mixed {
     String getP1();
     LocalDate getP2();
}
class CustomFeature1 {
      String getA1();
      String getB1();
}
class CustomFeature2 {
      String getA2();
      String getB2();
}

// O will have properties P1,P2,A1,A2,B1 and B2
MyObject o = new MyObject();
o.extend(CustomFeature1.class, new CustomFeature1());
o.extend(customFeature2.class, new CustomFeature2());
o.as(CustomFeature1.class).getCustomPropertyA1();

Se le proprietà personalizzate sono definite in fase di esecuzione, probabilmente, è il momento di pensare alle strutture dei dati di runtime definite da un metamodello:

interface Property {
    String getName();
    Class<?> getValueType();
    Object getValueFor(Object object);
}
interface Model {
     addProperty(String name, Class<?> valueType);
     List<Property> getProperties();
}
interface DynamicObject {
     Model getModel();
     Object getValue(String propertyName);
     void setValue(String propertyName, Object value);
}
class MyObject implements DynamicObject {
     String getP1();
     String getP2();
}

MyObject o = new MyObject();
// add new custom property
o.getModel().addProperty("A1", String.class);
// set custom property value
o.setValue("A1", "Lorem Ipsum");

// Let's list all custom properties and their values
for (Property property : o.getModel().getProperties()) {         
     System.out.println(property.getName() + "=" + property.getValueFor(o));
}

In entrambe le soluzioni è necessario implementare un meccanismo di persistenza personalizzato per archiviare i dati nel database o per serializzare in XML o JSON. Dovrai utilizzare la riflessione per questo.

    
risposta data 18.12.2015 - 12:48
fonte
0

Per i processi di evasione degli ordini in cui diversi tipi di ordine possono accadere a cose diverse, suggerisco di adottare un approccio orientato al servizio. Spostare la logica del dominio fuori dall'oggetto in servizi e aggiungere una cronologia eventi all'oggetto per memorizzare il suo stato variabile.

Ie. Invece di AdvanceOrder e SendNowOrder con metodi overridden Buy () hanno BuyNowService e PlaceAdvanceOrderService che hanno entrambi un metodo Buy (Order order).

È quindi possibile inviare gli ordini a uno o altro servizio come richiesto.

Invece di AdvanceOrder.DateToPlace e BuyNowOrder.IsInStock hanno DelayUntillEvent e OutOfStockEvent che ereditano da un evento di base e sono archiviati in Order.Events Solo i servizi che sanno come gestire questi eventi devono farvi riferimento.

    
risposta data 16.12.2015 - 01:52
fonte
0

Se la prestazione è l'obiettivo principale, allora opterei per la soluzione monolitica. Se la flessibilità è quella, allora potrebbe essere possibile utilizzare un dizionario chiamato "CustomProps" con il nome e il valore delle proprietà personalizzate e un altro chiamato "CustomFuncs" con il nome e la funzione che si desidera chiamare.

Ora puoi creare un getter / setter con un nome di stringa e un valore di oggetto, trovare la proprietà e trasmettere il valore. Per le funzioni analogiche con un nome stringa e una funzione / azione / delegato, che è possibile chiamare. Se hanno bisogno di parametri, questo può essere migliorato per questo.

Chiaramente, questo non sarà il più veloce, ma molto flessibile ...

    
risposta data 20.12.2015 - 16:00
fonte

Leggi altre domande sui tag