Versi Sederhana dari Pola Perintah GOF, dibuat untuk keperluan modernisasi proyek VCL. Juga menambahkan pabrik tindakan ke proyek ini, yang membungkus perintah menjadi tindakan VCL.

Proyek ini berisi dua versi implementasi pola:
ICommandTCommand berdasarkan TComponent Komponen TCommand dibuat untuk membantu modernisasi kode VCL Legacy . Ini membantu ekstraksi kode kusut, yang setelah mengamankannya dengan tes unit, dapat direfaktor menjadi lebih bersih dan lebih murah untuk mempertahankan kode yang berorientasi objek.
Komponen TCommand adalah objek transisi yang harus direktor setelah membersihkan kode yang diekstraksi dan setelah menghapus dependensi UI

Cara termudah untuk menggunakan komponen TCommand adalah dengan membuat kelas baru, menempelkan metode panjang ke dalam metode pelaksanaan dan menambahkan semua dependensi sebagai properti yang diterbitkan. Lihat Sampel Di Bawah.
Diagram Penggunaan TCommand dalam Aplikasi VCL:

Pengembang untuk membangun perintah baru perlu mendefinisikan kelas baru yang berasal dari TCommand (unit: Pattern.Command.pas ) dan mengimplementasikan metode yang dilindungi DoExecute , yang berisi logika perintah utama.
Pengembang dapat menerapkan metode DoGuard juga, yang disebut sebelum DoExecute dan memungkinkan untuk memverifikasi semua suntikan wajib (sistem injeksi dijelaskan di bawah). Biasanya semua suntikan diperiksa dengan Panggilan Assert.
Perintah sampel tanpa suntikan (penjaga kosong):
type
TDiceRollCommand = class (TCommand)
protected
procedure DoExecute ; override;
end ;
procedure TDiceRollCommand.DoExecute ;
begin
ShowMessage( ' Dice roll: ' +RandomRange( 1 , 6 ).ToString);
end ; Untuk mengeksekusi perintah, Anda harus membuat objek dan memanggil metode Publik Execute , yang memanggil DoGuard dan kemudian DoExecute :
cmd := TDiceRollCommand.Ceate(Self);
cmd.Execute; Komponen TCommand telah membangun sistem injeksi otomatis berdasarkan mekanisme RTTI klasik yang digunakan oleh perancang formulir IDE (Inspektur Objek). Properti yang terpapar disuntikkan harus didefinisikan pada bagian published dari komponen (perintah). Semua kelas berbasis komponen telah beralih pada pembuatan informasi tipe run-time selama proses kompilasi (opsi kompiler {$TYPEINFO ON} ). Terima kasih selama pembuatan perintah baru semua dependensi dapat dengan mudah disediakan dan ditugaskan ke properti yang diterbitkan secara otomatis. Informasi lebih lanjut tentang mesin RTTI klasik dapat ditemukan di dokumentasi Delphi: informasi jenis run-time
Perintah sampel dengan dua dependensi (satu diperlukan dan satu opsional):
type
TDiceRollCommand = class (TCommand)
const
RollCount = 100 ;
private
fOutput: TStrings;
fProgressBar: TProgressBar;
procedure ShowProgress (aRoll: integer);
protected
procedure DoGuard ; override;
procedure DoExecute ; override;
published
property OutputRolls: TStrings read fOutput
write fOutput;
property ProgressBar: TProgressBar read fProgressBar
write fProgressBar;
end ;
procedure TDiceRollCommand.DoGuard ;
begin
System.Assert(fOutput<> nil );
end ;
procedure TDiceRollCommand.ShowProgress (aRoll: integer);
begin
if Assigned(fProgressBar) then begin
if aRoll= 0 then
fProgressBar.Max := RollCount;
fProgressBar.Position := aRoll;
end ;
end
procedure TDiceRollCommand.DoExecute ;
begin
ShowProgress( 0 );
for var i := 0 to RollCount- 1 do
begin
fOutput.Add(RandomRange( 1 , 7 ).ToString);
ShowProgress(i+ 1 );
end ;
end ;Properti TCommand yang diterbitkan tersedia dicocokkan dengan jenis parameter yang dilewati dalam parameter (array terbuka). Aturan berikut digunakan oleh algoritma pencocokan:
Peringatan! Objek yang disuntikkan diakses oleh alamat dalam memori (pointer), terima kasih atas bahwa setiap perubahan yang dilakukan ke objek terlihat di dalam dan di luar tcommand. Jenis dan string sederhana diakses melalui nilai dan properti harus diperbarui secara manual untuk diperbarui.
Kode Sampel Suntikan Objek ke Properti TdicerollCommand:
cmd := TDiceRollCommand.Create(Self)
.Inject([Memo1.Lines,ProgressBar1]);Metode yang paling populer dan biasanya disarankan untuk menyuntikkan dependensi adalah injeksi konstruktor. Solusi ini diperkenalkan di sini (pola tcommand) adalah pendekatan berbasis komponen yang lebih. Pola ini lebih seperti tahap transisi yang memungkinkan dengan cepat mengekstrak dan menjalankan bagian -bagian penting dari aplikasi besar. Titik target akhir dalam proses itu adalah solusi arsitektur terbaik, berarti injeksi melalui konstruktor dan menggunakan antarmuka alih -alih objek.
TCommand.AdhocExecute<T> - Menjalankan perintah (membuat perintah, menyuntikkan dependensi mengeksekusi dan menghapus)Inject metode panggilanExecuteTCommandAction yang mengeksekusi perintah saat tindakan dipanggilTCommandAction adalah aksi VCL klasik Logika bisnis, diekstraksi ke dalam perintah, dapat dengan mudah dikonversi menjadi perintah asinkron, diproses dalam utas latar belakang yang terpisah. Mengganti kelas TCommand dengan TAsyncCommand pertama kali curam dalam transformasi seperti itu:
uses
Pattern.AsyncCommand;
type
TAsyncDiceRollCommand = class (TAsyncCommand)
...
end ; Meskipun perubahannya sangat sederhana, tetapi secara umum, pemrosesan multi-threaded adalah subjek yang jauh lebih serius dan membutuhkan pengetahuan yang lebih dalam tentang bidang ini. Dalam contoh ini ( TDiceRollCommand ) Dua topik bermasalah:
fProgressBar: TProgressBarfOutputRolls: TStringsAnda dapat dengan mudah menghadapinya, tetapi ini membutuhkan pengetahuan pemrosesan multithread yang lebih umum. Info lebih lanjut yang dapat Anda temukan dalam dokumentasi khusus: perintah asinkron
TCommandAction adalah kelas pembungkus berdasarkan TAction dan dapat menjalankan perintah berdasarkan kelas TCommand . Pengembang, saat membangun aplikasi VCL, dapat dengan mudah mengikat tindakan ini ke banyak kontrol (komponen visual yang didorong oleh tindakan atau tindakan sadar). Misalnya TCheckBox memiliki properti Action yang dieksekusi saat digunakan mengubah status kotak centang (dicentang). Tindakan memiliki beberapa keunggulan lain seperti Build in Notification System, justru dua mesin seperti itu: satu untuk memperbarui keadaan visual dan yang lain, lebih internal, untuk memberi tahu tentang penciptaan baru dan penghapusan komponen yang ada. Kedua mesin terlalu rumit untuk dijelaskan di bagian ini, informasi lebih lanjut dapat ditemukan dalam dokumentasi online Delphi.
Perspektif arsitektur bentuk yang TCommandAction dapat digunakan sebagai objek Invoker dan setelah migrasi dapat diganti dengan solusi khusus yang lebih elastis.
Contoh Konstruksi pada TCommandAction Invoker:
Button1.Action := TCommandAction.Create(Button1)
.WithCaption( ' Run sample command ' )
.WithCommand(TSampleCommand.Create(Button1))
.WithInjections([Memo1, Edit1]);| Metode utilitas | Keterangan |
|---|---|
WithCaption(aCaption) | Menetapkan keterangan tindakan yang ditampilkan dalam kontrol |
WithShortCut(aShortcut) | Menetapkan jalan pintas yang mengaktifkan suatu tindakan |
WithCommand(aCommand) | Mengatur perintah untuk mengeksekusi |
WithInjections(aInjections) | Menyuntikkan nilai ke dalam properti perintah |
WithEventOnUpdate(aProc) | Acara dipicu setelah Action Onupdate Event |
WithEventAfterExecution(aProc) | Acara dipicu saat perintah akan selesai |
Contoh Pengaturan Onupdate Event di TCommandAction :
Button2.Action := TCommandAction.Create(Self)
.WithCaption( ' Run sample command ' )
.WithCommand(MySampleCommand)
.WithEventOnUpdate(
procedure(cmd: TCommandAction)
begin
cmd.Enabled := CheckBox1.Checked;
end );Pola perintah memungkinkan pengembang untuk mengekstraksi kode bisnis yang berharga dan membuat aplikasi lebih sedikit digabungkan. Pengembang secara bersamaan masih dapat menggunakan praktik komponen terkenal dan menyusun kode yang lebih kompleks menggunakan komponen perintah. Pengembang bahkan dapat memperluas pola perintah dengan sifat dan acara mereka sendiri. Namun pendekatan ini adalah solusi sementara dan harus dikembangkan menjadi desain yang lebih berorientasi objek.
Pola perintah kompatibel dengan pola perintah GOF (lihat diagram di atas) dan dapat dimodernisasi. Moderasi ini harus dimulai ketika fase refactoring akan selesai dan logika akan ditutupi oleh tes unit. Selama refactoring semua dependensi visual harus dihapus, juga semua dependensi yang tidak relevan dan kode harus dipecah menjadi metode atau kelas yang lebih logis yang lebih kecil.
Setelah modernisasi, semua dependensi harus disuntikkan melalui konstruktor, perintah harus diakses melalui antarmuka, akses ke item internal perintah harus melalui metode pengambil dan setter. Objek yang disusun harus dibuat menggunakan wadah DI, seperti Metode Spring4D GlobalContainer .
Eksekusi Perintah Ad-Hoc (Buat, Suntikkan, Jalankan, Hapus)
TCommand.AdhocExecute<TSampleCommand>([Memo1, Edit1]);Membuat dependensi perintah dan suntikan:
cmdSampleCommand := TSampleCommand.Create(AOwner);
cmdSampleCommand.Inject([Memo1, Edit1]); Contoh Komponen TCommand :
type
TSampleCommand = class (TCommand)
private
FMemo: TMemo;
FEdit: TEdit;
protected
procedure DoGuard ; override;
procedure DoExecute ; override;
published
property Memo: TMemo read FMemo write FMemo;
property Edit: TEdit read FEdit write FEdit;
end ;
procedure TSampleCommand.DoGuard ;
begin
System.Assert(Memo<> nil );
System.Assert(Edit<> nil );
end ;
procedure TSampleCommand.DoExecute ;
begin
Memo.Lines.Add( ' Getting Edit text and put it here ... ' );
Memo.Lines.Add( ' * Edit.Text: ' +Edit.Text);
end ;