Reka bentuk dengan ahli statik

Walaupun Java banyak berorientasi objek, itu bukan bahasa yang berorientasikan objek murni . Salah satu sebab Java tidak berorientasikan objek semata-mata adalah bahawa tidak semua yang ada di dalamnya adalah objek. Sebagai contoh, Jawa membolehkan anda untuk mengisytiharkan pembolehubah jenis primitif ( int, float, boolean, dan lain-lain) yang tidak objek. Dan Java mempunyai medan dan kaedah statis, yang bebas dan terpisah dari objek. Artikel ini memberikan nasihat tentang cara menggunakan bidang dan metode statis dalam program Java, sambil mempertahankan fokus berorientasi objek dalam reka bentuk anda.

Jangka hayat kelas dalam mesin maya Java (JVM) mempunyai banyak persamaan dengan jangka hayat objek. Sama seperti objek yang dapat memiliki keadaan, yang diwakili oleh nilai-nilai pemboleh ubah contohnya, kelas dapat memiliki keadaan, yang diwakili oleh nilai-nilai pemboleh ubah kelasnya. Sama seperti JVM menetapkan pemboleh ubah contoh ke nilai awal lalai sebelum melaksanakan kod inisialisasi, JVM menetapkan pemboleh ubah kelas ke nilai awal lalai sebelum melaksanakan kod inisialisasi. Dan seperti objek, kelas boleh dikumpulkan sampah jika tidak lagi dirujuk oleh aplikasi yang sedang berjalan.

Walaupun begitu, terdapat perbezaan yang signifikan antara kelas dan objek. Mungkin perbezaan yang paling penting adalah cara kaedah contoh dan kaedah dipanggil: kaedah contoh (sebahagian besarnya) diikat secara dinamik, tetapi kaedah kelas terikat secara statik. (Dalam tiga kes khas, kaedah contoh tidak terikat secara dinamis: pemanggilan kaedah contoh persendirian, pemanggilan initkaedah (pembina), dan pemanggilan dengan superkata kunci. Lihat Sumber untuk maklumat lebih lanjut.)

Perbezaan lain antara kelas dan objek adalah tahap penyembunyian data yang diberikan oleh tahap akses peribadi. Sekiranya pemboleh ubah contoh dinyatakan peribadi, hanya kaedah contoh yang dapat mengaksesnya. Ini membolehkan anda memastikan integriti data instance dan menjadikan objek selamat di dalam benang. Selebihnya program tidak dapat mengakses pemboleh ubah instance secara langsung, tetapi mesti melalui kaedah contoh untuk memanipulasi pemboleh ubah instance. Dalam usaha menjadikan kelas berperilaku seperti objek yang dirancang dengan baik, anda boleh menjadikan pemboleh ubah kelas sebagai peribadi dan menentukan kaedah kelas yang memanipulasinya. Walaupun begitu, anda tidak mendapat jaminan keselamatan utuh atau bahkan integriti data dengan cara ini, kerana jenis kod tertentu mempunyai hak istimewa yang memberi mereka akses langsung ke pemboleh ubah kelas swasta: kaedah contoh,dan bahkan pemula pemboleh ubah contoh, dapat mengakses pemboleh ubah kelas peribadi itu secara langsung.

Oleh itu, medan dan kaedah kelas statik, walaupun serupa dalam banyak bidang dengan medan contoh dan kaedah objek, mempunyai perbezaan yang signifikan yang harus mempengaruhi cara anda menggunakannya dalam reka bentuk.

Melayan kelas sebagai objek

Semasa anda merancang program Java, anda mungkin akan menghadapi banyak situasi di mana anda merasakan keperluan untuk objek yang bertindak dalam beberapa cara seperti kelas. Anda mungkin, misalnya, menginginkan objek yang seumur hidupnya sesuai dengan kelas. Atau anda mungkin mahu objek yang, seperti kelas, mengehadkan dirinya pada satu kejadian dalam ruang nama tertentu.

Dalam situasi reka bentuk seperti ini, boleh menggoda untuk membuat kelas dan menggunakannya seperti objek untuk menentukan pemboleh ubah kelas, menjadikannya peribadi, dan menentukan beberapa kaedah kelas awam yang memanipulasi pemboleh ubah kelas. Seperti objek, kelas seperti itu mempunyai keadaan. Seperti objek yang dirancang dengan baik, pemboleh ubah yang menentukan keadaan adalah peribadi, dan dunia luar hanya dapat mempengaruhi keadaan ini dengan menggunakan kaedah kelas.

Malangnya, terdapat beberapa masalah dengan pendekatan "kelas-sebagai-objek" ini. Kerana kaedah kelas terikat secara statik, kelas-sebagai-objek anda tidak akan menikmati faedah fleksibiliti polimorfisme dan peningkatan. (Untuk definisi polimorfisme dan pengikatan dinamik, lihat artikel Teknik Reka Bentuk, Komposisi berbanding Pewarisan.) Polimorfisme dimungkinkan, dan disokong berguna, dengan pengikatan dinamik, tetapi kaedah kelas tidak terikat secara dinamis. Sekiranya seseorang mengklasifikasikan kelas anda sebagai objek, mereka tidak akan dapat mengatasi kaedah kelas anda dengan menyatakan kaedah kelas dengan nama yang sama; mereka hanya akan dapat bersembunyimereka. Apabila salah satu kaedah kelas yang didefinisikan semula dipanggil, JVM akan memilih pelaksanaan metode untuk dijalankan bukan oleh kelas objek pada waktu runtime, tetapi berdasarkan jenis pemboleh ubah pada waktu kompilasi.

Di samping itu, keselamatan benang dan integriti data yang dicapai oleh pelaksanaan kaedah kelas anda dengan teliti dalam kelas seperti objek anda seperti rumah yang dibina dari jerami. Keselamatan utas dan integriti data anda akan terjamin selagi semua orang menggunakan kaedah kelas untuk memanipulasi keadaan yang disimpan dalam pemboleh ubah kelas. Tetapi seorang pengaturcara yang cuai atau tidak mengerti boleh, dengan penambahan satu kaedah contoh yang mengakses pemboleh ubah kelas peribadi anda secara langsung, secara tidak sengaja membongkar dan membuang keselamatan thread dan integriti data anda.

Atas sebab ini, garis panduan utama saya mengenai pemboleh ubah kelas dan kaedah kelas adalah:

Jangan melayan kelas seperti objek.

Dengan kata lain, jangan merancang dengan medan statik dan kaedah kelas seolah-olah mereka adalah bidang contoh dan kaedah objek.

Sekiranya anda menginginkan keadaan dan tingkah laku yang seumur hidupnya sesuai dengan kelas, elakkan menggunakan pemboleh ubah kelas dan kaedah kelas untuk mensimulasikan objek. Sebagai gantinya, buat objek sebenar dan gunakan pemboleh ubah kelas untuk mengadakan rujukan kepadanya dan kaedah kelas untuk memberikan akses ke rujukan objek. Sekiranya anda ingin memastikan bahawa hanya satu keadaan dan keadaan yang wujud dalam satu ruang nama, jangan cuba merancang kelas yang mensimulasikan objek. Sebaliknya, buat singleton - objek yang dijamin hanya mempunyai satu contoh setiap ruang nama.

Oleh itu, apa yang sesuai untuk ahli kelas?

Pada pendapat saya, pemikiran yang terbaik untuk dipupuk semasa merancang program Java adalah dengan memikirkan objek, objek, objek. Fokus untuk merancang objek yang hebat, dan fikirkan kelas terutamanya sebagai cetak biru untuk objek - struktur di mana anda menentukan pemboleh ubah contoh dan kaedah contoh yang membentuk objek anda yang dirancang dengan baik. Selain itu, anda boleh menganggap kelas sebagai menyediakan beberapa perkhidmatan khas yang tidak dapat disediakan oleh objek, atau tidak dapat disediakan dengan elegan. Fikirkan kelas sebagai:

  • tempat yang tepat untuk menentukan "kaedah utiliti" (kaedah yang mengambil input dan memberikan output hanya melalui parameter lulus dan nilai kembali)
  • cara untuk mengawal akses ke objek dan data

Kaedah utiliti

Kaedah yang tidak memanipulasi atau menggunakan keadaan objek atau kelas yang saya panggil "kaedah utiliti." Kaedah utiliti hanya mengembalikan beberapa nilai (atau nilai) yang dikira semata-mata dari data yang dihantar ke kaedah sebagai parameter. Anda harus menjadikan kaedah sedemikian statik dan meletakkannya di kelas yang paling berkaitan dengan perkhidmatan yang disediakan oleh kaedah tersebut.

Contoh kaedah utiliti adalah String copyValueOf(char[] data)kaedah kelas String. Kaedah ini menghasilkan outputnya, nilai pengembalian jenis String, semata-mata dari parameter inputnya, susunan chars. Kerana copyValueOf()tidak menggunakan atau mempengaruhi keadaan objek atau kelas apa pun, itu adalah kaedah utiliti. Dan, seperti semua kaedah utiliti seharusnya, copyValueOf()adalah kaedah kelas.

Jadi salah satu kaedah utama untuk menggunakan kaedah kelas adalah sebagai kaedah utiliti - kaedah yang mengembalikan output yang dikira hanya dari parameter input. Penggunaan kaedah kelas yang lain melibatkan pemboleh ubah kelas.

Pemboleh ubah kelas untuk penyembunyian data

Salah satu prinsip asas dalam pengaturcaraan berorientasikan objek adalah penyembunyian data - menyekat akses ke data untuk meminimumkan pergantungan antara bahagian-bahagian program. Sekiranya sekeping data tertentu mempunyai aksesibilitas yang terbatas, data tersebut dapat berubah tanpa melanggar bagian program yang tidak dapat mengakses data tersebut.

Jika, misalnya, objek hanya diperlukan oleh keadaan kelas tertentu, rujukan ke objek tersebut dapat disimpan dalam pemboleh ubah kelas swasta. Ini memberikan semua contoh kelas ini akses mudah ke objek itu - contohnya menggunakannya secara langsung - tetapi tidak ada kod lain di tempat lain dalam program yang dapat menggunakannya. Dengan cara yang serupa, anda boleh menggunakan akses paket dan pemboleh ubah kelas terlindung untuk mengurangkan keterlihatan objek yang perlu dikongsi oleh semua anggota pakej dan subkelas.

Pemboleh ubah kelas awam adalah cerita yang berbeza. Sekiranya pemboleh ubah kelas awam tidak muktamad, itu adalah pemboleh ubah global: konstruk jahat yang merupakan antitesis penyembunyian data. Tidak pernah ada alasan untuk pemboleh ubah kelas awam, kecuali jika ia adalah muktamad.

Pemboleh ubah kelas awam akhir, sama ada jenis primitif atau rujukan objek, berfungsi dengan baik. Pemboleh ubah jenis primitif atau jenis Stringhanyalah pemalar, yang secara amnya membantu menjadikan program lebih fleksibel (lebih mudah diubah). Kod yang menggunakan pemalar lebih mudah diubah kerana anda boleh mengubah nilai pemalar di satu tempat. Pemboleh ubah kelas akhir jenis rujukan awam membolehkan anda memberi akses global ke objek yang diperlukan secara global. Sebagai contoh, System.in, System.out, dan System.erradalah awam pembolehubah kelas akhir yang memberi akses global kepada standard output input dan kesilapan sungai.

Oleh itu, kaedah utama untuk melihat pemboleh ubah kelas adalah sebagai mekanisme untuk membatasi kebolehcapaian (makna, menyembunyikan) pemboleh ubah atau objek. Apabila anda menggabungkan kaedah kelas dengan pemboleh ubah kelas, anda boleh melaksanakan dasar akses yang lebih rumit.

Menggunakan kaedah kelas dengan pemboleh ubah kelas

Selain bertindak sebagai kaedah utiliti, kaedah kelas dapat digunakan untuk mengawal akses ke objek yang disimpan dalam pemboleh ubah kelas - khususnya, untuk mengawal bagaimana objek dibuat atau dikendalikan. Dua contoh kaedah kelas seperti ini ialah kaedah setSecurityManager()dan getSecurityManager()kaedah kelas System. Pengurus keselamatan untuk aplikasi adalah objek yang, seperti aliran input, output, dan ralat standard, diperlukan di banyak tempat. Tidak seperti objek aliran I / O standard, bagaimanapun, rujukan kepada pengurus keselamatan tidak disimpan dalam pemboleh ubah kelas akhir awam. Objek pengurus keselamatan disimpan dalam pemboleh ubah kelas peribadi, dan kaedah set dan dapatkan menerapkan dasar akses khas untuk objek tersebut.

Model keselamatan Java meletakkan sekatan khas pada pengurus keselamatan. Sebelum Java 2 (sebelumnya dikenal sebagai JDK 1.2), aplikasi memulakan hidupnya tanpa pengurus keselamatan ( getSecurityManager()dikembalikan null). Panggilan pertama untuk setSecurityManager()menubuhkan pengurus keselamatan, yang selepas itu tidak dibenarkan untuk berubah. Sebarang panggilan berikutnya setSecurityManager()akan menghasilkan pengecualian keselamatan. Di Java 2, aplikasi selalu dimulakan dengan pengurus keselamatan, tetapi mirip dengan versi sebelumnya, setSecurityManager()kaedah ini memungkinkan anda untuk menukar pengurus keselamatan paling banyak sekali.

Pengurus keselamatan memberikan contoh yang baik tentang bagaimana kaedah kelas dapat digunakan bersama dengan pemboleh ubah kelas swasta untuk melaksanakan dasar akses khas untuk objek yang dirujuk oleh pemboleh ubah kelas. Selain kaedah utiliti, fikirkan kaedah kelas sebagai kaedah untuk menetapkan dasar akses khas untuk rujukan objek dan data yang disimpan dalam pemboleh ubah kelas.

Garis Panduan

Titik nasihat utama yang diberikan dalam artikel ini adalah:

Jangan melayan kelas seperti objek.

Sekiranya anda memerlukan objek, buatlah objek. Hadkan penggunaan pemboleh ubah dan kaedah kelas anda untuk menentukan kaedah utiliti dan melaksanakan jenis dasar akses khas untuk objek dan jenis primitif yang disimpan dalam pemboleh ubah kelas. Walaupun bukan bahasa yang berorientasikan objek yang murni, Java tetap berorientasikan objek untuk sebagian besar, dan reka bentuk anda harus menggambarkannya. Fikirkan objek.

Bulan depan

Artikel Teknik Reka Bentuk bulan depan adalah yang terakhir dari lajur ini. Saya akan mula menulis buku berdasarkan bahan Teknik Reka Bentuk, Java Fleksibel , dan akan meletakkan bahan itu di laman web saya semasa saya pergi. Oleh itu, sila ikuti projek itu dan hantarkan maklum balas kepada saya. Selepas berehat sebulan atau dua, saya akan kembali ke JavaWorld dan SunWorld dengan ruangan baru yang difokuskan pada Jini.

Permintaan untuk penyertaan pembaca

Saya menggalakkan komen, kritikan, cadangan, api - semua jenis maklum balas - mengenai bahan yang dibentangkan dalam lajur ini. Sekiranya anda tidak bersetuju dengan sesuatu, atau mempunyai sesuatu untuk ditambahkan, sila beritahu saya.

Anda boleh mengambil bahagian dalam forum perbincangan yang dikhaskan untuk bahan ini, memasukkan komen melalui borang di bahagian bawah artikel, atau e-mel saya secara langsung menggunakan pautan yang disediakan di bio saya di bawah.

Bill Venners telah menulis perisian secara profesional selama 12 tahun. Berpusat di Silicon Valley, dia menyediakan perkhidmatan perundingan dan latihan perisian dengan nama Artima Software Company. Selama bertahun-tahun ia telah mengembangkan perisian untuk industri elektronik, pendidikan, semikonduktor, dan insurans jiwa pengguna. Dia telah memprogram dalam banyak bahasa di banyak platform: bahasa pemasangan di berbagai mikropemproses, C di Unix, C ++ di Windows, Java di Web. Dia adalah pengarang buku Inside the Java Virtual Machine, yang diterbitkan oleh McGraw-Hill.