Els patrons de disseny són solucions provades a problemes comuns en el desenvolupament de programari. Aquests patrons ajuden a crear codi més organitzat, reutilitzable i mantenible. En aquest tema, explorarem alguns dels patrons de disseny més comuns i com implementar-los en Delphi/Object Pascal.
Introducció als Patrons de Disseny
Què són els Patrons de Disseny?
- Definició: Un patró de disseny és una solució general reutilitzable per a un problema comú en un context de disseny de programari.
- Categories: Els patrons de disseny es classifiquen en tres categories principals:
- Patrons Creacionals: Tracten amb la creació d'objectes.
- Patrons Estructurals: Tracten amb la composició d'objectes.
- Patrons de Comportament: Tracten amb la interacció entre objectes.
Beneficis dels Patrons de Disseny
- Reutilització del Codi: Faciliten la reutilització de solucions provades.
- Mantenibilitat: Milloren la mantenibilitat del codi.
- Comunicació: Proporcionen un llenguatge comú per als desenvolupadors.
Patrons Creacionals
Patró Singleton
El patró Singleton assegura que una classe només tingui una instància i proporciona un punt d'accés global a aquesta instància.
Implementació en Delphi
type
TSingleton = class
private
class var FInstance: TSingleton;
constructor Create; reintroduce;
public
class function GetInstance: TSingleton;
end;
constructor TSingleton.Create;
begin
inherited Create;
// Inicialització de l'objecte
end;
class function TSingleton.GetInstance: TSingleton;
begin
if not Assigned(FInstance) then
FInstance := TSingleton.Create;
Result := FInstance;
end;Explicació
- Constructor Privat: El constructor és privat per evitar la creació d'instàncies des de fora de la classe.
- Mètode Estàtic:
GetInstanceés un mètode estàtic que crea i retorna l'única instància de la classe.
Patró Factory
El patró Factory proporciona una interfície per crear objectes en una superclasse, però permet que les subclasses alterin el tipus d'objectes que es crearan.
Implementació en Delphi
type
TProduct = class
procedure Operation; virtual; abstract;
end;
TConcreteProductA = class(TProduct)
procedure Operation; override;
end;
TConcreteProductB = class(TProduct)
procedure Operation; override;
end;
TFactory = class
function CreateProduct(AType: string): TProduct;
end;
procedure TConcreteProductA.Operation;
begin
// Implementació específica de ProductA
end;
procedure TConcreteProductB.Operation;
begin
// Implementació específica de ProductB
end;
function TFactory.CreateProduct(AType: string): TProduct;
begin
if AType = 'A' then
Result := TConcreteProductA.Create
else if AType = 'B' then
Result := TConcreteProductB.Create
else
Result := nil;
end;Explicació
- Classe Producte:
TProductés una classe base amb un mètode abstracteOperation. - Classes Concretes:
TConcreteProductAiTConcreteProductBsón subclasses que implementenOperation. - Classe Fàbrica:
TFactoryconté el mètodeCreateProductque crea instàncies deTProductbasades en el tipus especificat.
Patrons Estructurals
Patró Adapter
El patró Adapter permet que classes amb interfícies incompatibles treballin juntes.
Implementació en Delphi
type
TTarget = class
procedure Request; virtual;
end;
TAdaptee = class
procedure SpecificRequest;
end;
TAdapter = class(TTarget)
private
FAdaptee: TAdaptee;
public
constructor Create(AAdaptee: TAdaptee);
procedure Request; override;
end;
procedure TTarget.Request;
begin
// Implementació per defecte
end;
procedure TAdaptee.SpecificRequest;
begin
// Implementació específica
end;
constructor TAdapter.Create(AAdaptee: TAdaptee);
begin
FAdaptee := AAdaptee;
end;
procedure TAdapter.Request;
begin
FAdaptee.SpecificRequest;
end;Explicació
- Classe Target:
TTargetdefineix l'interfície que el client espera. - Classe Adaptee:
TAdapteeconté una interfície incompatible que necessita ser adaptada. - Classe Adapter:
TAdapteradapta l'interfície deTAdapteea la interfície deTTarget.
Patrons de Comportament
Patró Observer
El patró Observer defineix una dependència un-a-molts entre objectes de manera que quan un objecte canvia d'estat, tots els seus dependents són notificats i actualitzats automàticament.
Implementació en Delphi
type
IObserver = interface
procedure Update;
end;
TSubject = class
private
FObservers: TList<IObserver>;
public
constructor Create;
destructor Destroy; override;
procedure Attach(AObserver: IObserver);
procedure Detach(AObserver: IObserver);
procedure Notify;
end;
TConcreteObserver = class(TInterfacedObject, IObserver)
public
procedure Update;
end;
constructor TSubject.Create;
begin
FObservers := TList<IObserver>.Create;
end;
destructor TSubject.Destroy;
begin
FObservers.Free;
inherited;
end;
procedure TSubject.Attach(AObserver: IObserver);
begin
FObservers.Add(AObserver);
end;
procedure TSubject.Detach(AObserver: IObserver);
begin
FObservers.Remove(AObserver);
end;
procedure TSubject.Notify;
var
Observer: IObserver;
begin
for Observer in FObservers do
Observer.Update;
end;
procedure TConcreteObserver.Update;
begin
// Implementació de l'actualització
end;Explicació
- Interfície Observer:
IObserverdefineix el mètodeUpdateque serà cridat perTSubject. - Classe Subject:
TSubjectmanté una llista d'observadors i els notifica quan hi ha un canvi d'estat. - Classe ConcreteObserver:
TConcreteObserverimplementa la interfícieIObserveri defineix el comportament de l'actualització.
Exercicis Pràctics
Exercici 1: Implementar un Singleton
Implementa una classe Singleton que gestioni la configuració de l'aplicació.
Exercici 2: Crear una Fàbrica
Crea una fàbrica que generi diferents tipus de documents (per exemple, PDF, Word).
Exercici 3: Utilitzar un Adapter
Implementa un Adapter per adaptar una classe de registre de logs a una interfície de registre existent.
Exercici 4: Implementar un Observer
Crea un sistema de notificacions on diversos observadors reben actualitzacions d'un subjecte.
Solucions
Solució 1: Singleton
type
TAppConfig = class
private
class var FInstance: TAppConfig;
constructor Create; reintroduce;
public
class function GetInstance: TAppConfig;
end;
constructor TAppConfig.Create;
begin
inherited Create;
// Inicialització de la configuració
end;
class function TAppConfig.GetInstance: TAppConfig;
begin
if not Assigned(FInstance) then
FInstance := TAppConfig.Create;
Result := FInstance;
end;Solució 2: Fàbrica
type
TDocument = class
procedure Open; virtual; abstract;
end;
TPDFDocument = class(TDocument)
procedure Open; override;
end;
TWordDocument = class(TDocument)
procedure Open; override;
end;
TDocumentFactory = class
function CreateDocument(AType: string): TDocument;
end;
procedure TPDFDocument.Open;
begin
// Obrir document PDF
end;
procedure TWordDocument.Open;
begin
// Obrir document Word
end;
function TDocumentFactory.CreateDocument(AType: string): TDocument;
begin
if AType = 'PDF' then
Result := TPDFDocument.Create
else if AType = 'Word' then
Result := TWordDocument.Create
else
Result := nil;
end;Solució 3: Adapter
type
TLogTarget = class
procedure LogMessage(AMessage: string); virtual;
end;
TLegacyLogger = class
procedure WriteLog(AMessage: string);
end;
TLogAdapter = class(TLogTarget)
private
FLegacyLogger: TLegacyLogger;
public
constructor Create(ALegacyLogger: TLegacyLogger);
procedure LogMessage(AMessage: string); override;
end;
procedure TLogTarget.LogMessage(AMessage: string);
begin
// Implementació per defecte
end;
procedure TLegacyLogger.WriteLog(AMessage: string);
begin
// Escriure log
end;
constructor TLogAdapter.Create(ALegacyLogger: TLegacyLogger);
begin
FLegacyLogger := ALegacyLogger;
end;
procedure TLogAdapter.LogMessage(AMessage: string);
begin
FLegacyLogger.WriteLog(AMessage);
end;Solució 4: Observer
type
IObserver = interface
procedure Update;
end;
TSubject = class
private
FObservers: TList<IObserver>;
public
constructor Create;
destructor Destroy; override;
procedure Attach(AObserver: IObserver);
procedure Detach(AObserver: IObserver);
procedure Notify;
end;
TConcreteObserver = class(TInterfacedObject, IObserver)
public
procedure Update;
end;
constructor TSubject.Create;
begin
FObservers := TList<IObserver>.Create;
end;
destructor TSubject.Destroy;
begin
FObservers.Free;
inherited;
end;
procedure TSubject.Attach(AObserver: IObserver);
begin
FObservers.Add(AObserver);
end;
procedure TSubject.Detach(AObserver: IObserver);
begin
FObservers.Remove(AObserver);
end;
procedure TSubject.Notify;
var
Observer: IObserver;
begin
for Observer in FObservers do
Observer.Update;
end;
procedure TConcreteObserver.Update;
begin
// Implementació de l'actualització
end;Conclusió
En aquest tema, hem explorat diversos patrons de disseny i com implementar-los en Delphi/Object Pascal. Els patrons de disseny són eines poderoses que poden millorar significativament la qualitat del teu codi. Practica aquests patrons amb els exercicis proporcionats per consolidar el teu coneixement i prepara't per aplicar-los en projectes reals.
Curs de Programació Delphi/Object Pascal
Mòdul 1: Introducció a Delphi/Object Pascal
- Introducció a Delphi i Object Pascal
- Configuració de l'Entorn de Desenvolupament
- Primera Aplicació Delphi
- Sintaxi i Estructura Bàsiques
- Variables i Tipus de Dades
Mòdul 2: Estructures de Control i Procediments
- Declaracions Condicionals
- Bucles i Iteració
- Procediments i Funcions
- Abast i Durada de les Variables
- Gestió d'Errors i Depuració
Mòdul 3: Treballant amb Dades
- Arrays i Cadenes
- Registres i Conjunts
- Tipus Enumerats i Subrang
- Gestió d'Arxius
- Accés a Bases de Dades
Mòdul 4: Programació Orientada a Objectes
- Introducció a la POO
- Classes i Objectes
- Herència i Polimorfisme
- Interfícies i Classes Abstractes
- Gestió d'Excepcions en POO
Mòdul 5: Funcions Avançades de Delphi
- Generics i Col·leccions
- Multifil i Programació Paral·lela
- Desenvolupament Basat en Components
- Biblioteca d'Execució de Delphi (RTL)
- Tècniques Avançades de Depuració
Mòdul 6: Desenvolupament d'Interfícies Gràfiques amb VCL i FMX
- Introducció a VCL
- Creació de Formularis i Controls
- Programació Basada en Esdeveniments
- Introducció a FireMonkey (FMX)
- Desenvolupament Multiplataforma amb FMX
Mòdul 7: Desenvolupament Web i Mòbil
- Desenvolupament Web amb Delphi
- Serveis RESTful
- Desenvolupament Mòbil amb Delphi
- Desplegament d'Aplicacions Mòbils
- Integració amb Serveis Web
Mòdul 8: Millors Pràctiques i Patrons de Disseny
- Organització del Codi i Documentació
- Patrons de Disseny en Delphi
- Tècniques de Refactorització
- Proves Unitàries i Desenvolupament Basat en Proves
- Optimització del Rendiment
