Dua metode penerapan mode Singleton di Delphi
haozi
Abstrak Artikel ini menjelaskan dua implementasi Delphi pada mode Singleton dan membuat analisis komparatif.
Pola desain kata kunci, Singleton
Pola Singleton adalah pola desain yang sangat berguna. Tujuannya hanyalah untuk membuat sebuah instance dari sebuah kelas dan menyediakan jalur akses global ke dalamnya. Variabel global membuat suatu objek mudah diakses, namun tidak menghalangi Anda untuk membuat instance beberapa objek. Tujuan dari pola tunggal adalah untuk memastikan bahwa hanya ada satu contoh selama siklus hidup program.
Lihatlah kode di bawah ini:
Prosedur TForm1.Button1Click(Pengirim: TObject);
var lS1 : TSingleton;
S2: TSingleton;
mulai
coba lS1 := TSingleton.Create; ////Panggil konstruktor kelas
lS2 := TSingleton.Create; ////Panggil konstruktor kelas
//// ...kode lain
Akhirnya
lS1.Gratis; ////Lepaskan objeknya
lS2.Gratis; ////Lepaskan objeknya
akhir;
akhir;
Dalam kode di atas, kelas TSingleton dipakai ketika fungsi Create dipanggil untuk pertama kalinya. lS1 menunjuk ke alamat objek penyimpanan memori. Ketika fungsi TSingleton.Create dipanggil untuk kedua kalinya, objek TSingleton berada kembali -dibuat. lS2 menunjuk ke alamat yang dialokasikan memori. Pola Singleton adalah membiarkan kelas itu sendiri bertanggung jawab untuk menyimpan satu-satunya instance-nya.
Dalam kode di atas, ketika ls2 dibuat, itu juga menunjuk ke objek yang ditunjuk oleh ls1 (yaitu, dialokasikan alamat memori yang sama). Demikian pula, kita harus mencegah pelepasan memori saat melepaskan ls1, karena single objek juga direferensikan oleh ls2. Hal ini memastikan bahwa hanya ada satu instance kelas selama siklus hidup program.
Kode contoh C++ dalam "Pola Desain" menggunakan variabel anggota statis C++ untuk menyimpan instance dan menggunakan fungsi konstruktor yang dilindungi. Namun, karena tidak ada variabel anggota statis di Delphi, metode contoh mode tunggal ini tidak dapat digunakan sebagaimana adanya. Di bawah ini kami menganalisis beberapa cara DELPHI mengimplementasikan mode Singleton.
satu. Metode berdasarkan penggantian dua fungsi virtual Tobject
fungsi kelas NewInstance: TObject virtual;
prosedur FreeInstance;
Fungsi NewInstance bertanggung jawab untuk mengalokasikan memori untuk objek ketika objek kelas dibuat, sedangkan FreeInstance melepaskan memori sebaliknya.
.
Yang pertama disebut ketika objek dibangun, dan yang terakhir disebut ketika objek tersebut dihancurkan.
Kami menggunakan dua variabel global untuk menampung objek tunggal dan jumlah referensi objek.
varInstance: TSingleton = nihil;
Hitung Ref: Integer = 0;
Unit kelas TSingleton:
////------------------------------- -- -----------
////
satuan uSingleton;
antarmuka
jenis
TSingleton = kelas(TObjek)
publik
fungsi kelas NewInstance: TObject override; ////Ganti fungsi kelas dasar
procedure FreeInstance; ////Ganti fungsi kelas dasar
fungsi kelas RefCount: Integer;////Mengembalikan jumlah referensi saat ini
akhir;
//// Deklarasi variabel global
var
Contoh: TSingleton = nihil;
Hitung Ref: Integer = 0;
pelaksanaan
{TSingleton}
prosedur TSingleton.FreeInstance;
mulai
Des( RefCount );////Kurangi jumlah referensi
if (RefCount = 0) maka////Apakah 0, jika ya, lepaskan memorinya
mulai
Contoh := nihil;
//// Lepaskan variabel privat dari kelas singleton
////…
FreeInstance yang diwarisi;
akhir;
akhir;
fungsi kelas TSingleton.NewInstance: TObject;
mulai
jika ( tidak Ditugaskan( Instance ) ) maka
mulai
Instance := TSingleton(mewarisi NewInstance);
////Contoh inisialisasi variabel privat:
//// Instance.VariableName := Nilai;
akhir;
Hasil := Contoh ;
Inc( Hitung Ref );
akhir;
fungsi kelas TSingleton.RefCount: Integer;
mulai
Hasil := RefCount;
akhir;
akhir.
////------------------------------- -- -----------
////
Ketika konstruktor TSingleton dipanggil, fungsi override NewInstance kami akan dipanggil, dan NewInstance akan mengalokasikan memori dan mengembalikannya ke konstruktor. Dengan cara ini, melalui fungsi override NewInstance, kami memastikan bahwa fungsi Create hanya dapat membuat instance objek TSingleton. (tidak peduli berapa kali dipanggil) Create hanya mengembalikan alamat memori yang dialokasikan untuk pertama kalinya). Pada saat yang sama variabel RefCount menampung berapa banyak referensi yang kita miliki ke objek tersebut.
Mari kita lihat kode pengujiannya
prosedur TForm1.Button1Click(Pengirim: TObject);
var
lS1, lS2: TSingleton;
Ob1, Ob2: Objek;
mulai
lS1 := TSingleton.Buat;
TampilkanPesan(IntToStr(RefCount)); //// Ref_Count = 1
lS2 := TSingleton.Buat;
TampilkanPesan(IntToStr(RefCount)); //// Ref_Count = 2
Ob1 := TObject.Create;
Ob2 := Tobject.Create;
jika lS1 = lS2 maka
ShowMessage('Alamat sama') //// lS1 = lS2
kalau tidak
ShowMessage('Alamat tidak sama');
jika Ob1 = Ob2 maka
ShowMessage('Alamat sama')
kalau tidak
ShowMessage('Alamat tidak sama'); //// Ob1 <> Ob2
akhir;
Ketika program memanggil destruktor (yaitu ketika fungsi GRATIS dipanggil), destruktor akan memanggil fungsi FreeInstance untuk melepaskan memori yang dialokasikan oleh konstruktor. Fungsi FreeInstance Override memastikan bahwa memori objek mode tunggal dilepaskan hanya ketika jumlah referensi mencapai nol.
Ini kode pengujian kami:
var
lS1: TSingleton;
lS2: TSingleton;
mulai
mencoba
lS1 := TSingleton.Create; ////Panggil konstruktor kelas
lS2 := TSingleton.Create; ////Panggil konstruktor kelas
//// ...kode lain
Akhirnya
lS1.Free; ////Di sini pertama-tama kita akan memanggil FreeInstance yang ditentukan oleh override kita,
////Karena RefCount adalah 1 setelah dikurangi 1 saat ini, objek tunggal belum dilepaskan.
lS2.Free; ////dec(RefCount)= 0 melepaskan objek tunggal
akhir;
akhir;
Metode implementasi pola tunggal di atas adalah cara yang baik untuk menyadari bahwa kelas itu sendiri bertanggung jawab untuk menyimpan instance uniknya sendiri (dengan mencegat permintaan untuk membuat objek baru - lihat "Pola Desain". Metode ini tidak memiliki batasan khusus dalam penggunaan dari kelas TSingleton - —Pemrogram dapat memanggil fungsi Buat dan Gratis sesuka hati.
Kerugian dari mode ini adalah kelas TSingleton tidak dapat diwarisi sebagai kelas induk untuk menghasilkan subkelas. Jika pewarisan menghasilkan dua subkelas, hanya satu objek yang akan dihasilkan selama Pembuatan.
prosedur TForm1.Button1Click(Pengirim: TObject);
var
lS1: subkategori satu;
lS2: subkategori dua;
mulai
lS1 := Subkelas 1.Buat;
lS2 := Subkelas 2.Buat; ////Subkelas 2 tidak akan dibuat, lS2 akan menunjuk ke memori yang ditunjuk oleh lS1,
//// Yaitu, lS1 = lS2end;
dua. Implementasi Delphi dari contoh di "Pola Desain"
Contoh implementasi "Pola Desain" adalah mengontrol hanya satu instance objek melalui fungsi konstruktor pribadi. Namun, implementasi kode C++ yang diberikan tidak memberikan cara objek dilepaskan. Fungsi Create tidak dapat diprivatisasi di Delphi. Kami mendefinisikan fungsi baru untuk menggantikan fungsi Create dan melindungi fungsi Create dari kelas induk. Kodenya adalah sebagai berikut
:
////------------------------------- -- -----------
////
satuan uSingletonUnit;
antarmuka
kegunaan
Kelas, SysUtils;
jenis
TCSingleton = class(TComponent) ////Diwarisi dari kelas Tcomponent.
pribadi
konstruktor CreateInstance(AOwner: TComponent); ////Lewati parameter Pemilik
//// Dengan cara ini, objek kelas TCSingleton akan dimusnahkan bersama dengan Pemiliknya (pemilik bertanggung jawab untuk menghancurkan objek TCSingleton)
publik
Buat konstruktor (Pemilik: TComponent);
Contoh fungsi kelas (Pemilik: TComponent): TCSingleton;
akhir;
var
gCSingleton: TCSingleton; //// Variabel global
pelaksanaan
{TCSingleton}
konstruktor TCSingleton.Create(Pemilik: TComponent);
mulai
////Melindungi fungsi dari fungsi Buat
naikkan Exception.CreateFmt('akses kelas %s melalui Instance saja',
[Nama Kelas]);
akhir;
konstruktor TCSingleton.CreateInstance(Pemilik: TComponent);
mulai
////Konstruktor yang baru didefinisikan adalah Pribadi
Warisan Buat(Pemilik);
akhir;
fungsi kelas TCSingleton.Instance(Pemilik: TComponent): TCSingleton;
mulai
jika tidak Ditugaskan (gCSingleton) maka
gCSingleton := TCSingleton.CreateInstance(AOpemilik);
Hasil := gCSingleton;
akhir;
akhir.
////------------------------------- -- -------------/
/
Selama penggunaan kelas implementasi di atas, pemrogram tidak perlu mempertimbangkan penghancuran objek mode tunggal. Itu tidak bisa memanggil Buat, Anda harus memanggil fungsi Instance untuk mendapatkan instance objek, dan meneruskan pemilik tunggal sebagai parameter ke fungsi tersebut. Metode implementasi ini dapat diwarisi sebagai kelas dasar dan digunakan dalam pola keadaan tunggal (lihat Referensi 4) untuk mencapai polimorfisme waktu eksekusi.
tiga. Kesimpulan
Implementasi Delphi dari mode Singleton juga dapat ditemukan di Internet. Ada dua metode implementasi lainnya dalam artikel ini
Yang paling umum dan sederhana. Pada saat yang sama, ide metode lain juga sangat mirip dengan kedua metode di atas.