Saya menerapkan bot IRC yang menerima pesan dan saya memeriksa pesan itu untuk menentukan fungsi mana yang harus dihubungi. Apakah ada cara yang lebih pintar untuk melakukan ini? Sepertinya akan cepat lepas kendali setelah aku bangun untuk menyukai 20 perintah.
Mungkin ada cara yang lebih baik untuk abstrak ini?
public void onMessage(String channel, String sender, String login, String hostname, String message){
if (message.equalsIgnoreCase(".np")){
// TODO: Use Last.fm API to find the now playing
} else if (message.toLowerCase().startsWith(".register")) {
cmd.registerLastNick(channel, sender, message);
} else if (message.toLowerCase().startsWith("give us a countdown")) {
cmd.countdown(channel, message);
} else if (message.toLowerCase().startsWith("remember am routine")) {
cmd.updateAmRoutine(channel, message, sender);
}
}
java
design
abstraction
Harrison Nguyen
sumber
sumber
Jawaban:
Gunakan tabel pengiriman . Ini adalah tabel yang berisi pasangan ("bagian pesan",
pointer-to-function
). Operator kemudian akan terlihat seperti ini (dalam kode semu):(
equalsIgnoreCase
dapat ditangani sebagai kasus khusus di suatu tempat sebelumnya, atau jika Anda memiliki banyak tes tersebut, dengan tabel pengiriman kedua).Tentu saja, apa yang
pointer-to-function
harus terlihat tergantung pada bahasa pemrograman Anda. Berikut ini adalah contoh dalam C atau C ++. Di Java atau C # Anda mungkin akan menggunakan ekspresi lambda untuk tujuan itu, atau Anda mensimulasikan "pointer-to-functions" dengan menggunakan pola perintah. Buku online gratis " Perl Pesanan Tinggi " memiliki bab lengkap tentang tabel pengiriman menggunakan Perl.sumber
equalsIgnoreCase
untuk "bermain sekarang" tetapitoLowerCase().startsWith
untuk yang lain.toLowerCase
operasi keluar dari loop.Saya mungkin akan melakukan sesuatu seperti ini:
Kemudian Anda dapat meminta setiap perintah mengimplementasikan antarmuka ini, dan mengembalikan true ketika cocok dengan pesan.
sumber
Command
lebih mandiri jika tahu kapan harus dipanggil sendiri. Memang menghasilkan sedikit overhead jika daftar perintah sangat besar tapi itu mungkin diabaikan.equals
danhashCode
harus sama dengan string yang mewakili perintahAnda menggunakan Java - jadi buatlah itu indah ;-)
Saya mungkin akan melakukan ini menggunakan Anotasi:
Buat Anotasi Metode kustom
Tambahkan Anotasi ke semua Metode yang relevan di Kelas misalnya
Di konstruktor Anda gunakan Refleksi untuk membuat HashMap Metode dari semua Metode yang dijelaskan di kelas Anda:
Dalam
onMessage
Metode Anda , lakukan saja perulangancommandList
mencoba mencocokkan String pada masing-masing dan memanggil dimethod.invoke()
mana cocok.sumber
Bagaimana jika Anda mendefinisikan antarmuka, katakanlah
IChatBehaviour
yang memiliki satu metode yang disebutExecute
yang mengambil dalammessage
dancmd
objek:Di kode Anda, Anda kemudian mengimplementasikan antarmuka ini dan menentukan perilaku yang Anda inginkan:
Dan seterusnya untuk yang lainnya.
Di kelas utama Anda, Anda kemudian memiliki daftar perilaku (
List<IChatBehaviour>
) yang diterapkan bot IRC Anda. Anda kemudian dapat menggantiif
pernyataan Anda dengan sesuatu seperti ini:Di atas akan mengurangi jumlah kode yang Anda miliki. Pendekatan di atas juga akan memungkinkan Anda untuk memasok perilaku tambahan ke kelas bot Anda tanpa memodifikasi kelas bot itu sendiri (sesuai dengan
Strategy Design Pattern
).Jika Anda hanya ingin satu perilaku diaktifkan pada satu waktu, Anda dapat mengubah tanda tangan
execute
metode untuk menghasilkantrue
(perilaku telah dipecat) ataufalse
(perilaku tidak menyala) dan mengganti loop di atas dengan sesuatu seperti ini:Hal di atas akan lebih membosankan untuk diimplementasikan dan diinisialisasi karena Anda perlu membuat dan lulus semua kelas tambahan, namun, itu akan membuat bot Anda mudah diperluas dan dimodifikasi karena semua kelas perilaku Anda akan dienkapsulasi dan semoga independen satu sama lain.
sumber
if
? Yaitu, bagaimana Anda memutuskan suatu perilaku dieksekusi untuk suatu perintah?if
bagian dalam perilaku).IChatBehaviour
dapat menangani perintah yang diberikan, karena memungkinkan penelepon untuk melakukan lebih banyak dengan itu, seperti memproses kesalahan jika tidak ada perintah yang cocok, meskipun itu benar-benar hanya preferensi pribadi. Jika itu tidak diperlukan, maka tidak ada gunanya rumit kode."Cerdas" dapat (setidaknya) tiga hal:
Performa Lebih Tinggi
Saran Tabel Pengiriman (dan yang setara) adalah saran yang bagus. Tabel seperti itu disebut "CADET" pada tahun-tahun yang lalu untuk "Tidak Dapat Menambahkan; Bahkan Tidak Mencoba." Namun, pertimbangkan komentar untuk membantu pengelola pemula tentang cara mengelola tabel tersebut.
Maintabilitas
"Jadikan indah" bukanlah peringatan kosong.
dan, sering diabaikan ...
Kegembiraan
Penggunaan toLowerCase memiliki jebakan di mana beberapa teks dalam beberapa bahasa harus mengalami restrukturisasi yang menyakitkan ketika mengubah antara magiscule dan miniscule. Sayangnya, jebakan yang sama ada untuk toUpperCase. Berhati-hatilah.
sumber
Anda bisa meminta semua perintah mengimplementasikan antarmuka yang sama. Kemudian parser pesan dapat mengembalikan Anda perintah yang sesuai yang hanya akan Anda jalankan.
Sepertinya lebih banyak kode. Ya, Anda masih perlu mem-parsing pesan untuk mengetahui perintah mana yang harus dieksekusi tetapi sekarang sudah pada titik yang ditentukan dengan benar. Ini dapat digunakan kembali di tempat lain. (Anda mungkin ingin menyuntikkan MessageParser tapi itu masalah lain. Juga, pola Flyweight mungkin merupakan ide yang baik untuk perintah, tergantung pada berapa banyak yang Anda harapkan akan dibuat.)
sumber
Apa yang akan saya lakukan adalah ini:
Ini akan membuat ini lebih mudah dikelola. Lebih banyak manfaatnya ketika jumlah 'lain jika' tumbuh terlalu banyak.
Tentu saja, terkadang memiliki 'jika ada' ini tidak akan menjadi masalah besar. Saya kira 20 tidak seburuk itu.
sumber