Шаблони в delphi


Шаблони в Delphi

Шаблони в DelphiШаблони програмування (Design Patterns) - це часто використовувані в процесі програмування структури, залежно та зв'язку в об'єктно-орієнтованому проектуванні. Знання, як правильно і найбільш корисно використовувати шаблони, може допомогти вам проектувати свої додатки краще, використовувати більш компактний, структурований код багаторазового використання. Також це буде сприяти розробці великих і складних систем.

Delphi - це об'єктно-орієнтована мова, в якому присутня безліч класів (об'єктів) та певних залежностей, які вже реалізовані і готові до вживання, що допомагає спростити і полегшити розробку додатків. Але найбільш важливими залежностями в світлі об'єктної моделі шаблонів є: успадкування класів, віртуальні (virtual) і абстраткние (abstract) методи, використання захищеного (protected) і загальнодоступного (public) визначення методів. Все це дозволяє створювати шаблони програмування, які можна використовувати багато разів і легко розширювати їх можливості. Так само, як будь-який об'єктно-орієнтована мова, Delphi дозволяє підвищити функціональність і стабільність шаблонів шляхом ізоляції основних властивостей і методів від їх побратимів, які можуть піддатися модифікації.
І найпростіший приклад - це сама Delphi, що розширюється середовище розробки, завдяки своїй пакетної архітектурі, інтерфейсів середовища розробки (IDE) і інтерфейсів інструментів (Tools). Ці інтерфейси визначають безліч абстрактних і віртуальних конструкторів і операцій (методів), які широко використовуються як при написанні програмного забезпечення, так і при розширенні самого середовища розробки (написання своїх компонентів, майстрів, експертів).
Хочу зауважити, що в цій статті багато назв і визначення представлені "як є". Я порахував це більш зручним, ніж займатися перекладом назв шаблонів та інших термінів на російську, так як не завжди можна передати точне визначення при перекладі, а зміст терміну втрачати не хотілося б. Так що тут і далі всі назви шаблонів залишені на англійській мові, як, втім, і вихідний код прикладів, хоча я допускаю, що, можливо, в інших джерелах, відмінних від моїх, назви і терміни можуть варіюватися. Але нехай це вас не бентежить, тому що з опису згодом стане зрозуміло про призначення кожного окремо взятого шаблону. Також перераховані шаблони не претендують на звання повного переліку шаблонів. Вони просто відображають мої знання в цій галузі з тих джерел, що будуть перераховані нижче.
Список деяких часто використовуваних шаблонів (всього їх більше сорока) представлений в таблиці.

Засвідчується, що даний клас має тільки один екземпляр. Надає глобальну інформацію для доступу до класу.

Конвертує інтерфейс класу в інший інтерфейс, зрозумілий клієнтові шаблону. Adapter дозволяє класам з різними інтерфейсами спільно працювати, що неможливо в звичайних умовах через відмінності в інтерфейсах.

Визначає каркас (Skeleton) алгоритму або його частини в глобальній операції, дозволяючи розбивати виконання на кілька кроків, передаючи його подклассам. Тобто підкласи отримують можливість перевизначити деякі кроки алгоритму без зміни всієї структури алгоритму.

Відокремлює створення об'єкта від його практичного уявлення так, що один конструктор може створювати різні уявлення об'єкта.

Надає механізм створення сімейства пов'язаних між собою або залежних один від одного об'єктів, не вимагаючи при цьому опису конкретних класів.

Визначає інтерфейс, що дозволяє створити об'єкт, але дає можливість подклассам вирішувати, який клас реалізувати. Factory Method дозволяє класу мати підкласи, тобто нащадків.

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TCSingleton = class (TComponent)
private

protected

public

constructor Create (AOwner: TComponent); override; // перекриваємо конструктор
destructor Destroy; override; // перекриваємо деструктор

var Global_CSingleton: TCSingleton;
Global_OSingleton: TOSingleton;

procedure Register;
begin
RegisterComponents ( 'Patterns', [TCSingleton, TOSingleton]); // описані компоненти будуть зареєстровані і поміщені на закладці Patterns.
end;

constructor TCSingleton.Create (AOwner: TComponent);
begin
if Global_CSingleton <> nil then // перевіряємо єдиність створюваного компонента
begin
ShowMessage ( 'Компонент вже існує! Ви не можете створювати більше одного такого компонента.'); // якщо він вже існує, то користувач отримує відмову в створенні ще одного примірника
Abort // перериваємо виконання без будь-яких повідомлень про помилку
end
Else begin
inherited Create (AOwner); // інакше створюємо об'єкт
Global_CSingleton: = Self; // і передаємо на нього посилання
end;
end;

destructor TCSingleton.Destroy;
begin
if Global_CSingleton = Self then // якщо існує об'єкт, який потрібно знищити
Global_CSingleton: = nil; // то знищуємо його
inherited Destroy; // викликаємо зовнішній деструктор
end;

constructor TOSingleton.Create (AOwner: TComponent);
begin
if Global_OSingleton <> nil then
begin
ShowMessage (Об'єкт уже існує! Ви не можете створювати більше одного такого об'єкта. ');
Abort
end
Else begin
inherited Create (AOwner);
Global_OSingleton: = Self;
end;
end;

destructor TOSingleton.Destroy;
begin
if Global_OSingleton = Self then
Global_OSingleton: = nil;
inherited Destroy;
end;

uses SysUtils, Classes;

FCustomerID: Longint;
FFirstName: string;
FLastName: string;
FDOB: TDateTime;

function GetCustomerID: Longint; virtual;
function GetFirstName: string; virtual;
function GetLastName: string; virtual;
function GetDOB: TDateTime; virtual;

constructor Create (CustID: Longint); virtual;
property CustomerID: Longint read GetCustomerID;
property FirstName: string read GetFirstName;
property LastName: string read GetLastName;
property DOB: TDateTime read GetDOB;

function GetCustomer (CustomerID: Longint): TNewCustomer;

constructor TNewCustomer.Create (CustID: Longint);

begin
FCustomerID: = CustID;
FFirstName: = 'A';
FLastName: = 'New_Customer';
FDOB: = Now;
еnd;

function TNewCustomer.GetCustomerID: Longint;

function TNewCustomer.GetFirstName: string;
begin
Result: = FFirstName;
end;

function TNewCustomer.GetLastName: string;
begin
Result: = FLastName;
end;

function TNewCustomer.GetDOB: TDateTime;
begin
Result: = FDOB;
end;

TOldDOB = record
Day: 0..31;
Month: 1..12;
Year: 0..99;
end;

FCustomerID: Integer;
FName: string;
FDOB: TOldDOB;

constructor Create (CustID: Integer);
property CustomerID: Integer read FCustomerID;
property Name: string read FName;
property DOB: TOldDOB read FDOB;

constructor TOldCustomer.Create (CustID: Integer);

begin
FCustomerID: = CustomerID;
FName: = 'An Old_Customer';
with FDOB do begin
Day: = 1;
Month: = 1;
Year: = 1;
end;
end;

function GetCustomerID: Longint; override;
function GetFirstName: string; override;
function GetLastName: string; override;
function GetDOB: TDateTime; override;

constructor Create (CustID: Longint); override;
destructor Destroy; override;

constructor TAdaptedCustomer.Create (CustID: Longint);

begin
inherited Create (CustID);
FOldCustomer: = TOldCustomer.Create (CustID);
end;

destructor TAdaptedCustomer.Destroy;
begin
FOldCustomer.Free;
inherited Destroy;
end;

function TAdaptedCustomer.GetCustomerID: Longint;

function TAdaptedCustomer.GetFirstName: string;
var SpacePos: integer;

function TAdaptedCustomer.GetLastName: string;
var SpacePos: integer;

function TAdaptedCustomer.GetDOB: TDateTime;
var FullYear: Word;

function GetCustomer (CustomerID: Longint): TNewCustomer;

begin
if CustomerID> Last_OldCustomer_In_Database then
Result: = TNewCustomer.Create (CustomerID)
else
Result: = TAdaptedCustomer.Create (CustomerID) as TNewCustomer;
end;

Таким чином, клас TАdaptedCustomer існує як прошарок між двома іншими класами, забезпечуючи їх нормальну взаємодію - перетворення даних в зрозумілий новим класом формат.
Це одні з найпростіших шаблонів. Як я вже писав, всього їх близько 40, але я не буду настільки поширюватися, і в наступній статті ми розглянемо ще декілька шаблонів, більш складних, ніж наведені вище. Проте, чим вище їх складність, тим більшу користь вони можуть принести вам при використанні в ваших розробках. І чим швидше ви навчитеся використовувати отримані знання з користю, тим простіше і легше стане вам працювати, програмувати.

Денис Мигачев АКА Denver

Схожі статті