Alla classe Shelf descritta nei post precedenti, oggi
aggiungiamo un po' di carne sul fuoco. Lo scopo è quello di presentare la classe
Book e di fare qualche precisazione riguardante la classe
Shelf, dato che
studiando la serializzazione ho cambiato un po' le carte in tavola e sono state
fatte diverse modifiche al codice in modo da renderlo più pulito e più
"standard" rispetto alle design guidelines di Microsoft. Un grazie a Michele, a
Marco e ad Andrea per avermi
risposto
sul forum di
UGIdotNET.
In fondo a questo post trovate il download del file ZIP
contenente il codice C# di quanto descritto qui sotto. Il codice rappresenta già
un primo blocco funzionante di quanto abbiamo fatto sinora: generics, interfacce
e via dicendo. Adesso mi preme dare una descrizione della vista d'insieme di tutte le classi coinvolte, dandone una spiegazione logica e
dal punto di vista del codice.
Struttura delle classi
Quello che a me piace chiamare
'oggetto root' della nostra applicazione è rappresentato dalla classe
Storage. Tale classe aderisce al design-pattern Singleton: in ogni momento in cui la
nostra applicazione sta girando, avremo sempre e soltanto una sola
istanza di questa classe. La classe Storage espone una
sola proprietà Shelves, che rappresenta a tutti gli effetti una collection di
singoli oggetti Shelf.
La seconda classe di cui abbiamo bisogno è il singolo Shelf, di cui abbiamo già parlato nei post
precedenti. Tale classe ha due sole proprietà: Name e Books. La prima è una
banale proprietà di tipo string ("Mensola in salotto"),
mentre la seconda è una collection di singoli oggetti Book.
La terza classe Book non ha
bisogno di molte spiegazioni, il nome è già abbastanza chiaro. La classe Book
espone le proprietà Title, Author,
Pages, InLoan, Bookmark e
Chapters. Rispettivamente: titolo, autore, pagine totali, un
bool che indica se è in prestito a qualcuno, un int che fa da segnalibro e una collection di Chapter. Questa
classe implementa le interfacce IEquatable<Book>, ICloneable e
un'interfaccia custom IPaper che vedremo più avanti nei
prossimi post (e che comunque è disponibile nel codice scaricabile sin da
oggi).
La quarta classe Chapter espone
una sola proprietà Title di tipo string.
Le classi Collection esposte dai singoli oggetti
Nel
paragrafo qui sopra ho accennato al fatto che, ad esempio, la classe Book espone
una collection di Chapter. Non è del tutto esatto. Così facendo infatti avremmo
diversi problemi di serializzazione, di design e mancanza di aderenza agli
standard. La cosa migliore è quello di creare una classe che erediti da
Collection<object>, dove object sta per Shelf, Book e
Chapter. Vediamo nel dettaglio la questione.
Prima abbiamo detto che ogni Book espone una collection di Chapter.
L'implementazione è stata realizzata in questo modo:
public class Book : IEquatable<Book>, IPaper, ICloneable
{
private string _Title;
private string _Author;
private int _Pages;
private bool _InLoan;
private int _Bookmark;
private ChapterCollection _Chapters;
}
Notare la presenza della property Chapters
(implementata più avanti tramite il get/set) di tipo ChapterCollection.
L'implementazione delle classi collection che mi servono è la seguente:
using System.Collections.ObjectModel;
public class ChapterCollection : Collection<Chapter> { }
public class BookCollection : Collection<Book> { }
public class ShelfCollection : Collection<Shelf> { }
Riassumendo: la classe Storage espone una property
ShelfCollection, la classe Shelf espone una property
BookCollection e la classe Book espone una property
ChapterCollection.
Questo design ci permette di scrivere codice molto efficiente, pulito e
user-friendly, come questo:
// Creo un unico oggetto Storage
Storage camera = Storage.Instance;
// Creo un oggetto Shelf
Shelf mensola = new Shelf();
mensola.Name = "Mensola in salotto";
// Creo 3 Books
Book l1 = new Book("La Spada di Shannara");
Book l2 = new Book("Le Pietre Magiche di Shannara");
Book l3 = new Book("La Canzone di Shannara");
// Al primo libro aggiungo 2 Chapter
l1.Chapters.Add(new Chapter("Prologo"));
l1.Chapters.Add(new Chapter("Inizio"));
// Metto i 3 Books allo Shelf
mensola.Books.Add(l1);
mensola.Books.Add(l2);
mensola.Books.Add(l3);
// Allo storage aggiunge l'unico Shelf creato
camera.Shelves.Add(mensola);
Download del codice
Come promesso, metto
disponibile il codice scritto finora [MCPD.ZIP,
~47KB].
Ricordo che è compilabile con VS2005 e con il FX2.0.
Nel prossimo post vedremo il meccanismo di serializzazione e deserializzazione delle nostre classi,
un altro argomento molto importante preso in considerazione dall'esame
70-536.