martedì 18 dicembre 2007

Polimorfismo

Nella maggior parte dei casi utilizziamo questo concetto senza averne la piena percezione.
Alla lettera polimorfismo vuol dire "aver molte forme", questa informazione anche se "open",
implica che la capacità di assumere forme di verse potrebbe dipendere dall'oggetto stesso,
o da chi lo crea.

Da qui in avanti il discorso potrebbe prendere due direzioni ben distinte, la prima è del
tutto filosofica e concettuale, dove l'avere molte forme potrebbe implicare il "quando" o
"per quanto". Oppure sfociare in un esempio pratico.

La definizione "avere molte forme" nasconde il fatto che la base potrebbe avere un forma
ma non essere del tutto completa o "completabile".
E' quindi necessario ricorrere per l'implementazione di questo esempio ad una classe di tipo
Asrtatta, in modo da fornire un indicazione dei metodi o un base degli stessi, che potranno o
dovranno essere estesi.

In molti sul Web propongono come Esempio "le figure giometriche" che rendono molto bene
l'idea del funzionamento del polimorfismo, di contro preferisco fare un esempio legato ad
un contesto già più evoluto.

L'idea che vogliamo implementare ha quest'aspetto :



//
// classe Entity
// Rappresenta un Utente
//
public class UserApplicationCredential
{
#region Private
private string _Name = "";
private string _Surname = "";
private string _Login = "";
private string _Password = "";
#endregion

#region Public
// read only
public string Name
{
get { return _Name; }
}
// read only
public string Surname
{
get { return _Surname; }
}

public string Login
{
get { return _Login; }
set { _Login = value; }
}

public string Password
{
get { return _Password; }
set { _Password = value; }
}
#endregion

#region Builder
public UserApplicationCredential(string sName, string sSurname)
{
this._Name = sName;
this._Surname = sSurname;
}
#endregion
}

//
// classe Abstract
// classe che diverrà polimorfica.
//
public abstract class DefaultUser
{
// rappresentazione interna delle credenziali
public UserApplicationCredential _UserCredential;

// processo di creazione di un utente
public abstract UserApplicationCredential UserCredential(string sName, string sSurname);

// processo di verifica
public abstract bool Exist();

// logica di Validazione
public abstract bool DoLogin(string sLogin, string sPassword);
}

//
// classe di validazione utente per DataBase
//
public class DataBaseUser:DefaultUser
{

public override UserApplicationCredential UserCredential(string sName, string sSurname)
{
return new UserApplicationCredential(sName, sSurname);
}

public override bool Exist()
{
//
// logica di ricerca
//
if ((_UserCredential.Name != "") && (_UserCredential.Surname != ""))
{
return FindUser();
}

return false;
}

public override bool DoLogin(string sLogin, string sPassword)
{
//
// logica di validazione
//
return true;

}

private bool FindUser()
{
//
// Si connetterà al DB
// Eseguirà la Query di ricerca
// Tornerà true o false se ha trovato l'utente.
//

return true;
}
}

//
// classe di validazione utente per LDaP
//
public class LDaPUser : DefaultUser
{

public override UserApplicationCredential UserCredential(string sName, string sSurname)
{
return new UserApplicationCredential(sName, sSurname);
}

public override bool Exist()
{
//
// crea un oggetto Active Directory
// Esegue la query di Ricerca
// Distrugge l'oggetto di Actice Directory
//

return true;
}

public override bool DoLogin(string sLogin, string sPassword)
{
//
// crea un oggetto Active Directory
// Esegue la query di Ricerca per tutti i campi
// Distrugge l'oggetto di Actice Directory
//

return true;
}
}

//
// classe di validazione INTERNA all'applicazione
//
public class ApplicationUser : DefaultUser
{
//
// non l'ho implementato ma si suppone che quest'array
// si popolato dal costruttore.
//
private UserApplicationCredential[] _Users = new UserApplicationCredential[10];


public override UserApplicationCredential UserCredential(string sName, string sSurname)
{
return new UserApplicationCredential(sName, sSurname);
}

public override bool Exist()
{
//
// cerca Name e Surname
//
for (int i = 0; i < _Users.Length; i++)
{
if (
(_UserCredential.Name == _Users[i].Name) &&
(_UserCredential.Surname == _Users[i].Surname)
)
{
return true;
}
}
return false;
}

public override bool DoLogin(string sLogin, string sPassword)
{

//
// cerca per tutti i campi
//
for (int i = 0; i < _Users.Length; i++)
{
if (
(_UserCredential.Name == _Users[i].Name) &&
(_UserCredential.Surname == _Users[i].Surname) &&
(_UserCredential.Password == _Users[i].Password) &&
(_UserCredential.Login == _Users[i].Login)
)
{
return true;
}
}
return false;
}
}

Che cosa abbiamo creato ?
Una classe entità il cui scopo è quello di avere una definizione comune di utente per tutte le classi.

Una classe astratta che rappresenta la base dell'oggetto polimorfico.

Tre classi che ereditano l'oggeto base e compio azioni Differenti fra loro per la validazione dell'utente.

Attenzione Queste classi in realtà non fanno nulla si tratta solo di esempi molto sbrigativi.

Adesso passiamo al main o all'entry point del nostro applicativo.

class Program
{
static void Main(string[] args)
{
string userName = "";
string userSurname = "";
string userLogin = "";
string userPassword = "";

Console.WriteLine("Insert Name and Surname");
userName = Console.ReadLine();
userSurname = Console.ReadLine();


DefaultUser _DefUser;

//
// nessun parametro usiamo gli utenti dell'applicazione
//
if (args[0]=="")
{
_DefUser = new ApplicationUser();
}

//
// è stata richiesta una validazione Ldap
//
if (args[0].ToLower() == "-ldap")
{
_DefUser = new LDaPUser();
}

//
// è stata richiesa la validazione su DB.
//
if (args[0].ToLower() == "-db")
{
_DefUser = new DataBaseUser();
}

//
// necessaria (forse no)
//
if (_DefUser != null)
{
_DefUser.UserCredential(userSurname, userSurname);

if (_DefUser.Exist())
{
Console.WriteLine("Insert Login and Password");
userLogin = Console.ReadLine();
userPassword = Console.ReadLine();

_DefUser.DoLogin(userLogin, userPassword);
}
}
}
}

Che cosa abbiamo fatto ?
Abbiamo ipotizzato che per la nostra suluzione l'utente debba per prima cosa immettere il nome ed il cognome.
Quindi verifichiamo negli argomenti se è stata specificata una modalità di validazione dell'utente...

Ed è proprio nell'atto di "create" dell'oggetto _DefUser decidiamo il tipo di validatore che utilizzeremo.

In conclusione l'oggetto _DefUser può assumere aspetti di concetto simili ma di comportamento differente.

Nessun commento: