Patterns
1 - Factory Pattern
Il Factory Pattern fornisce un’interfaccia per creare famiglie di oggetti connessi o dipendenti tra loro, in modo che non ci sia necessità da parte
dei client di specificare i nomi delle classi concrete all’interno del proprio codice.
Questo pattern ha lo scopo di astrarre la costruzione di un oggetto e la sua composizione, garantendo una maggiore flessibilità e sopratutto riducendo
la dipendenza della classe client, cioè quella che usa l’oggetto, dalla classe richiesta, cioè quella prodotta dal Factory Pattern.
Il pattern può rivelarsi utile quando una classe non è in grado di conoscere a priori il tipo di oggetti da creare.
L’applicazione del pattern consente di eliminare le dipendenze dai tipi concreti utilizzati.
Un esempio tipico è quello della connessione ad un database. Un software, grazie all’ausilio di classi/driver (Concrete Products) potrebbe essere in grado
di utilizzare un database qualsiasi.
Di seguito il diagramma UML delle classi che realizzano il Factory Pattern:

Product definisce l’interfaccia implementata da ConcreteProduct; Creator definisce il FactoryMethod che restituisce una interfaccia di tipo Product e ConcreteCreator ridefinisce il factory method per restituire ConcreteProduct.
Analisi del codice
Il programma utilizza il Factory Pattern per leggere una configurazione generica e convertirla in XML.
Come esempio sono state introdotti tre ConcreteCreator (Creator_Configuration_T1, Creator_Configuration_T2 e Creator_Configuration_T3) che implementano
l'interfaccia 'IConfigurationCreator' e si occupano di instanziare una classe ConcreteProduct (Configuration_T1_Key, Configuration_T2_Key e Configuration_T3_Key),
che implementa 'IConfiguration' e si occupa di leggere una configurazione di un certo tipo da uno stub restituendola in formato XML.
Per evidenziare ciò che accade c'è una form con quattro bottoni che creano differenti classi ConcreteCreator che vengono poi utilizzate dal metodo
"ShowConfiguration(...)" per instanziare il ConcreteProduct e mostrare la configurazione ottenuta; nel caso del quarto bottone, la form stessa viene
modificata in base alla configurazione ottenuta.
using System;
namespace Factory.Classes
{
/// <summary>
/// A 'ConcreteCreator' class
/// </summary>
public class Creator_Configuration_T1_Key : IConfigurationCreator
{
public IConfiguration FactoryConfiguration()
{
return new Configuration_T1_Key();
}
}
}
using System;
namespace Factory.Classes
{
/// <summary>
/// A 'Concrete Product' class
/// </summary>
class Configuration_T1_Key : AConfiguration
{
public override string LoadConfiguration(string Key, string User)
{
Stub_DB.GetValuesFromConfiguration(Key, User, ref ConfEnabled, ref ConfValue);
BaseConfiguration(ref xmlConfiguration, Key, ConfEnabled, ConfValue);
return xmlConfiguration.OuterXml;
}
}
}
Di seguito l'evento onclick del quarto bottone, che carica dallo stub una configurazione contenente tra l'altro delle informazioni di stile, le mostra utilizzando ShowConfiguration(...), quindi ridisegna la form in base allo stile ottenuto:
private void ShowConfiguration(IConfiguration concreteConfiguration, string Key)
{
string xmlConfiguration = concreteConfiguration.LoadConfiguration(Key, "001");
// Parse xml string
XmlDocument xmlConfDocument = new XmlDocument();
xmlConfDocument.LoadXml(xmlConfiguration);
// Reading "base" tags
if (xmlConfDocument.GetElementsByTagName("Enabled").Count > 0)
lbEnabled.Text =
xmlConfDocument.GetElementsByTagName("Enabled").Item(0).InnerText;
else
lbEnabled.Text = "***";
if (xmlConfDocument.GetElementsByTagName("Value").Count > 0)
lbValue_A.Text =
xmlConfDocument.GetElementsByTagName("Value").Item(0).InnerText;
else
lbValue_A.Text = "***";
// Other tags
if (xmlConfDocument.GetElementsByTagName("Value2").Count > 0)
lbValue_B.Text =
xmlConfDocument.GetElementsByTagName("Value2").Item(0).InnerText;
else
lbValue_B.Text = "***";
// Style tags
if (xmlConfDocument.GetElementsByTagName("Style").Count > 0)
{
Control TaggedC = null;
// Is the tagged element the form ?
if (this.Tag != null)
{
if (this.Tag.ToString().Trim() == Key)
TaggedC = this;
}
if (TaggedC == null)
{
// Look for every tagged control style
foreach (Control C in Controls)
{
if (C.Tag != null)
{
if (C.Tag.ToString().Trim() == Key)
{
TaggedC = C;
break;
}
}
}
}
// Todo: class to perfom style application to control
// Style will be parsed directly in the form object, not in the business class
if (TaggedC != null)
{
if (xmlConfDocument.GetElementsByTagName("TagVisible").Count > 0)
TaggedC.Visible = Convert.ToBoolean(
xmlConfDocument.GetElementsByTagName("TagVisible").Item(0).InnerText);
if (xmlConfDocument.GetElementsByTagName("TagEnabled").Count > 0)
TaggedC.Enabled = Convert.ToBoolean(
xmlConfDocument.GetElementsByTagName("TagEnabled").Item(0).InnerText);
if (xmlConfDocument.GetElementsByTagName("TagHeight").Count > 0)
TaggedC.Height = Convert.ToInt16(
xmlConfDocument.GetElementsByTagName("TagHeight").Item(0).InnerText);
if (xmlConfDocument.GetElementsByTagName("TagWidth").Count > 0)
TaggedC.Width = Convert.ToInt16(
xmlConfDocument.GetElementsByTagName("TagWidth").Item(0).InnerText);
}
}
lb_ConcreteName.Text = concreteConfiguration.GetType().Name;
}
...
private void btnConfig4_Click(object sender, EventArgs e)
{
IConfigurationCreator configurationCreator = new Creator_Configuration_T3_Key();
IConfiguration concreteConfiguration = configurationCreator.FactoryConfiguration();
// Look for form style
if (this.Tag != null)
{
ShowConfiguration(concreteConfiguration, this.Tag.ToString().Trim());
}
// Look for every tagged control style
foreach (Control C in Controls)
{
if (C.Tag != null)
{
ShowConfiguration(concreteConfiguration, C.Tag.ToString().Trim());
}
}
}