Saya sedang mengerjakan kode UI di mana saya memiliki Action
kelas, sesuatu seperti ini -
public class MyAction extends Action {
public MyAction() {
setText("My Action Text");
setToolTip("My Action Tool tip");
setImage("Some Image");
}
}
Ketika kelas Action ini dibuat, cukup banyak diasumsikan bahwa Action
kelas tidak akan dikustomisasi (dalam arti - teks, tooltip atau gambar tidak akan diubah di mana pun dalam kode). Sekarang, kita perlu mengubah teks tindakan di beberapa lokasi dalam kode. Jadi, saya menyarankan rekan kerja saya untuk menghapus teks tindakan hardcode dari konstruktor dan menerimanya sebagai argumen, sehingga semua orang dipaksa untuk melewati teks tindakan. Sesuatu seperti kode di bawah ini -
public class MyAction extends Action {
public MyAction(String actionText) {
setText(actionText);
setTooltip("My Action tool tip");
setImage("My Image");
}
}
Dia, bagaimanapun, berpikir bahwa karena setText()
metode milik kelas dasar dapat secara fleksibel digunakan untuk melewatkan teks tindakan di mana pun instance tindakan dibuat. Dengan begitu, tidak perlu mengubah MyAction
kelas yang ada . Jadi kodenya akan terlihat seperti ini.
MyAction action = new MyAction(); //this creates action instance with the hardcoded text
action.setText("User required new action text"); //overwrite the existing text.
Saya tidak yakin apakah itu cara yang benar untuk menangani masalah. Saya pikir dalam kasus yang disebutkan di atas pengguna tetap akan mengubah teks, jadi mengapa tidak memaksanya saat membangun tindakan? Satu-satunya manfaat yang saya lihat dengan kode asli adalah pengguna dapat membuat kelas Tindakan tanpa banyak berpikir tentang pengaturan teks.
Jawaban:
Itu sebenarnya bukan manfaat, untuk sebagian besar tujuan itu adalah kelemahan dan dalam kasus yang tersisa saya akan menyebutnya dasi. Bagaimana jika seseorang lupa memanggil setText () setelah konstruksi? Bagaimana jika itu adalah kasus dalam beberapa kasus yang tidak biasa, mungkin penangan kesalahan? Jika Anda ingin benar-benar memaksa teks untuk ditetapkan, Anda harus memaksanya pada waktu kompilasi, karena hanya kesalahan waktu kompilasi yang berakibat fatal . Apa pun yang terjadi pada saat run-time tergantung pada jalur kode tertentu yang sedang dieksekusi.
Saya melihat dua jalur yang jelas ke depan:
null
atau string kosong, tetapi kemudian fakta bahwa Anda tidak menetapkan teks lebih eksplisit daripada implisit. Sangat mudah untuk melihat keberadaannull
parameter dan melihat bahwa mungkin ada beberapa pemikiran yang dimasukkan ke dalamnya, tetapi tidak begitu mudah untuk melihat kurangnya pemanggilan metode dan menentukan apakah kurangnya seperti itu disengaja atau tidak. Untuk kasus sederhana seperti ini, ini mungkin pendekatan yang akan saya ambil.sumber
Overloading konstruktor akan menjadi solusi sederhana dan langsung di sini:
Itu lebih baik daripada menelepon
.setText
nanti, karena dengan cara ini tidak ada yang perlu ditimpa,actionText
dapat menjadi hal yang dimaksudkan sejak awal.Ketika kode Anda berkembang dan Anda akan membutuhkan lebih banyak fleksibilitas (yang pasti akan terjadi), Anda akan mendapat manfaat dari pola pabrik / pembangun yang disarankan oleh jawaban lain.
sumber
Tambahkan metode 'setText' yang lancar:
Apa yang bisa lebih jelas dari itu? Jika Anda memutuskan untuk menambahkan properti lain yang dapat disesuaikan, tidak ada masalah.
sumber
setText()
didefinisikan pada kelas Action yang diwarisi dari MyAction. Kemungkinan sudah memiliki jenis void return.Sama seperti kata kevin cline dalam jawabannya, saya pikir cara untuk pergi adalah membuat API yang lancar . Saya hanya ingin menambahkan bahwa API lancar berfungsi lebih baik ketika Anda memiliki lebih dari satu properti yang dapat Anda gunakan.
Ini akan membuat kode Anda lebih mudah dibaca, dan dari sudut pandang saya lebih mudah dan, aham , "seksi" untuk menulis.
Dalam kasus Anda itu akan seperti ini (maaf untuk kesalahan ketik apa pun, sudah setahun sejak saya menulis program java terakhir saya):
Dan penggunaannya akan seperti ini:
sumber
Saran untuk menggunakan konstruktor atau pembangun baik-baik saja secara umum, tetapi, dalam pengalaman saya, kehilangan beberapa poin utama untuk Tindakan, yang
Saya sangat menyarankan agar nama, tooltip, ikon dll ... dibaca dari file properti, XML, dll. Misalnya, untuk tindakan File-Open, Anda bisa mengirimkan Properties dan akan mencari
Ini adalah format yang cukup mudah untuk diterjemahkan ke bahasa Prancis, untuk mencoba ikon baru yang lebih baik, dll. Tanpa waktu programmer atau kompilasi ulang.
Ini hanya garis besar kasar, banyak yang tersisa untuk pembaca ... Carilah contoh internasionalisasi lainnya.
sumber
Tidak berguna untuk memanggil setText (actionText) atau setTooltip ("Tip alat tindakan saya") di dalam konstruktor; lebih mudah (dan Anda mendapatkan lebih banyak kinerja) jika Anda langsung menginisialisasi bidang yang sesuai:
Jika Anda mengubah actionText selama masa hidup objek terkait MyAction, Anda harus menempatkan metode setter; jika tidak menginisialisasi bidang hanya dalam konstruktor tanpa menyediakan metode penyetel.
Karena tooltip dan gambar adalah konstanta, perlakukan mereka sebagai konstanta; memiliki bidang:
Sebenarnya, ketika mendesain objek umum (bukan kacang atau objek yang mewakili struktur data ketat) adalah ide yang buruk untuk menyediakan setter dan getter, karena mereka semacam memecah enkapsulasi.
sumber
Saya pikir ini benar jika kita akan membuat kelas tindakan umum (seperti pembaruan, yang digunakan untuk memperbarui Karyawan, Departemen ...). Itu semua tergantung skenario. Jika kelas tindakan tertentu (seperti karyawan pembaruan) (digunakan banyak tempat dalam aplikasi - Perbarui karyawan) dibuat dengan niat untuk menyimpan teks, tooltip, dan gambar yang sama di setiap tempat dalam aplikasi (untuk sudut pandang konsistensi). Jadi hardcoding dapat dilakukan untuk teks, tooltip dan gambar untuk menyediakan teks, tooltip dan gambar default. Masih untuk memberikan lebih banyak fleksibilitas, untuk menyesuaikan ini, harus ada metode setter yang sesuai. Mengingat hanya 10% tempat yang harus kita ubah. Mengambil teks tindakan setiap saat dari pengguna dapat menyebabkan teks berbeda setiap kali untuk tindakan yang sama. Seperti 'Perbarui Emp', 'Perbarui Karyawan', 'Ubah Karyawan' atau 'Edit Karyawan'.
sumber
Pikirkan bagaimana mesin virtual akan digunakan dan gunakan solusi yang akan memandu, atau bahkan memaksa, pengguna untuk menggunakan mesin virtual tersebut dengan cara yang benar, atau setidaknya yang terbaik. Seorang programmer yang menggunakan kelas ini akan memiliki banyak hal lain yang perlu dikhawatirkan dan dipikirkan. Kelas ini tidak boleh ditambahkan ke daftar.
Misalnya, jika kelas MyAction seharusnya tidak dapat diubah setelah konstruksi (dan mungkin inisialisasi lainnya), seharusnya tidak memiliki metode penyetel. Jika sebagian besar waktu akan menggunakan "Teks Tindakan Saya" default, harus ada konstruktor tanpa parameter, ditambah konstruktor yang memungkinkan teks opsional. Sekarang pengguna tidak perlu berpikir untuk menggunakan kelas dengan benar 90% dari waktu. Jika pengguna biasanya harus memikirkan teks, lewati konstruktor tanpa parameter. Sekarang pengguna dipaksa untuk berpikir bila perlu dan tidak bisa mengabaikan langkah yang diperlukan.
Jika sebuah
MyAction
instance harus bisa berubah setelah konstruksi penuh maka Anda memerlukan setter untuk teks. Sangat menggoda untuk melewatkan pengaturan nilai dalam konstruktor (prinsip KERING - "Don't Repeat Yourself") dan, jika nilai default biasanya cukup baik, saya akan melakukannya. Tetapi jika tidak, mengharuskan teks di konstruktor memaksa pengguna untuk berpikir kapan mereka harus.Perhatikan bahwa pengguna ini tidak bodoh . Mereka hanya memiliki terlalu banyak masalah nyata untuk dikhawatirkan. Dengan memikirkan "antarmuka" kelas Anda, Anda dapat mencegahnya menjadi masalah nyata - dan yang tidak perlu.
sumber
Dalam solusi yang diusulkan berikut, superclass adalah abstrak dan memiliki ketiga anggota diatur ke nilai default.
Subclass memiliki konstruktor yang berbeda sehingga programmer dapat membuat instance.
Jika konstruktor pertama digunakan, semua anggota akan memiliki nilai default.
Jika konstruktor kedua digunakan, Anda memberikan nilai awal untuk anggota actionText meninggalkan dua anggota lainnya dengan nilai default ...
Jika konstruktor ketiga digunakan, Anda instantiate dengan nilai baru untuk actionText dan toolTip, meninggalkan imageURl dengan nilai default ...
Dan seterusnya.
sumber