Saya telah tertarik pada pola desain untuk sementara waktu dan mulai membaca "Pola Desain Kepala Pertama". Saya mulai dengan pola pertama yang disebut pola 'Strategi'. Saya membahas masalah yang diuraikan dalam gambar di bawah ini dan pertama kali mencoba mengusulkan solusi sendiri sehingga saya benar-benar dapat memahami pentingnya pola.
Jadi pertanyaan saya adalah mengapa solusi saya untuk masalah di bawah ini tidak cukup baik. Apa poin baik / buruk dari solusi saya vs polanya? Apa yang membuat pola itu jelas satu-satunya solusi yang bisa dilakukan?
SOLUSI SAYA
Kelas Induk: DUCK
<?php
class Duck
{
public $swimmable;
public $quackable;
public $flyable;
function display()
{
echo "A Duck Looks Like This<BR/>";
}
function quack()
{
if($this->quackable==1)
{
echo("Quack<BR/>");
}
}
function swim()
{
if($this->swimmable==1)
{
echo("Swim<BR/>");
}
}
function fly()
{
if($this->flyable==1)
{
echo("Fly<BR/>");
}
}
}
?>
KELAS INHERIT: MallardDuck
<?php
class MallardDuck extends Duck
{
function MallardDuck()
{
$this->quackable = 1;
$this->swimmable = 1;
}
function display()
{
echo "A Mallard Duck Looks Like This<BR/>";
}
}
?>
KELAS Warisan: WoddenDecoyDuck
<?php
class WoddenDecoyDuck extends Duck
{
function woddendecoyduck()
{
$this->quackable = 0;
$this->swimmable = 0;
}
function display()
{
echo "A Wooden Decoy Duck Looks Like This<BR/>";
}
}
design-patterns
Imran Omar Bukhsh
sumber
sumber
Jawaban:
Kode Anda akan pecah ketika, misalnya bebek dukun dengan suara yang berbeda. Boolean hanya akan menyebabkan boolean lain menjadi pernyataan if yang sangat berbulu.
Namun, pola strateginya sederhana. Ambil contoh ini metode quack dan letakkan di kelas atau antarmuka itu sendiri. Antarmuka di php akan menjadi kelas yang tidak mengandung implementasi apa pun selain metode yang bertopik (yaitu tidak ada yang terjadi ketika Anda memanggilnya).
Dengan begitu Anda dapat membuat beberapa implementasi quackable:
Dan karena kami melakukannya dengan bijaksana, kami dapat menambahkan lebih banyak jenis "perdukunan":
Hal yang sama dapat diterapkan untuk metode terbang dan berenang untuk kelas Bebek. Cara Anda mengimplementasikan kelas Duck dengan quackable akan seperti ini (antarmuka quackable disediakan melalui konstruktor, yang merupakan semacam cara kerja ketergantungan injeksi):
Menerapkan bebek mallard dan bebek umpan akan mudah karena Anda hanya perlu menyediakan jenis dukun apa yang harus dilakukan bebek:
Menggunakan itu semua sederhana:
Saya harap ini semua masuk akal bagi Anda.
sumber
Pertama-tama, masalah Anda tidak ada hubungannya dengan pola strategi. Ide dari pola strategi adalah faktor tanggung jawab untuk perilaku tertentu ke dalam kelas yang berbeda. Dengan begitu, Anda bisa mencolokkan perilaku yang berbeda menjadi satu instance pada saat run time.
Sekarang solusi Anda bekerja dengan cukup baik untuk skenario yang Anda masuki, tetapi skenario itu hanya latihan, yang cukup jauh dari masalah dunia nyata.
Jika Anda menggunakan teknik ini untuk menangani proyek-proyek besar, Anda berisiko berakhir dengan 5-10 lapisan warisan, di mana setiap subkelas digabungkan ke semakin banyak bendera. Kode seperti itu sangat rapuh dan verbal. Mengotak-atik keadaan internal semua kelas super bukanlah cara OOP menangani hal-hal seperti itu, karena mengaburkan pemisahan masalah.
Solusi menggunakan antarmuka secara signifikan lebih bersih, lebih kuat dan dengan demikian akan terbukti lebih dapat dipertahankan dari waktu ke waktu. Cobalah untuk tidak membuat bebek pangkalan serba guna umum, tetapi membuat abstraksi yang jelas tentang berbagai aspek bebek yang berbeda. Saya baru saja membuat posting blog tentang hal ini, Anda mungkin menemukan bermanfaat.
sumber
RuberBall
? AkankahRuberDuck
juga memiliki metode roll kosong?Ah, pertanyaan bagus. Saya tidak berpikir itu adalah praktik yang sangat baik untuk memiliki variabel anggota yang mengubah fungsi. Terutama masalah dengan solusi ini adalah bahwa karena Anda mengekspos
fly
danquack
metode diDuck
kelas itu akan tampak bahwa Anda mengatakan bahwa "Semua bebek bisafly
/quack
." Apa yang lebih buruk adalah itu, tergantung pada jenis runtime dari contoh bebek yang saya miliki,fly
atauquack
mungkin atau mungkin tidak melakukan apa-apa. Ini dapat menyebabkan kode yang sangat membingungkan.Sedangkan, dalam contoh yang diberikan buku, saat Anda mengharapkan bebek yang bisa terbang, Anda bisa mengetik (atau menguji, karena Anda menggunakan bahasa dinamis) jika itu
Flyable
bebek.Jika setiap kali saya memiliki bebek, sebelum saya memanggilnya
quack
saya harus memutuskan harus memeriksa apakah variabel anggota yang dapat diterbangkan diatur ke true yang akan menyebabkan banyak duplikasi kode.The
Flyable
antarmuka membantu membangun harapan. Ya,quack
metode default Anda akan memeriksa apakah seharusnya atau tidak, tetapi saya, sebagai penelepon, tidak memiliki jaminan bahwa itu bahkan aman untuk dipanggilquack
. Juga pikirkan skenario denganRubberDucky
yang harus mencicit daripada dukun. Ketika Anda menggantiquack
metode Anda harus tahu untuk memeriksa$quackable
variabel anggota sebelum Anda mengambil tindakan apa pun.Hal lain yang saya pikir membuat solusi ini tidak jelas adalah karena Anda menggunakan bahasa dinamis seperti PHP, itu membuat pengaturan ekspektasi tentang tipe input menjadi sulit. (Bukan berarti ada yang salah dengan ini, tetapi bahasa yang diketik secara statis mungkin membuatnya lebih mudah untuk dipahami.)
Saya harap ini membantu dan masuk akal.
sumber
Kode Anda akan menjadi berantakan dengan cepat jika Anda telah mengatakan 10 jenis bebek yang berbeda yang semuanya memiliki kombinasi berbeda dari 3 varian terbang, dukun, dan berenang.
Secara pribadi, saya menemukan bahwa nilai sebenarnya dari pola strategi menjadi jelas ketika saya mulai menulis tes unit dan menggunakan injeksi ketergantungan. Jika Anda tidak menggunakannya, Anda akan mengalami banyak masalah dalam mengelola dependensi dan karenanya membuat objek dalam pengujian Anda.
Anda akan sampai pada situasi di mana membuat bebek menjadi rumit, maka Anda mungkin ingin menulis unit test untuk beberapa metode quacking atau terbang, tetapi Anda tidak dapat melakukannya tanpa membuat bebek dalam tes Anda.
sumber
Memiliki keadaan boolean untuk menyimpan apakah bebek dapat dukun / terbang, adalah solusi yang sangat spesifik untuk masalah khusus yang Anda hadapi dalam desain kelas Anda dan mungkin tidak berlaku untuk kasus-kasus lain di mana pola strategi sesuai.
Saya pikir pendekatan 'quackable' Anda membuat kode sedikit lebih berbelit-belit. Ini satu hal lagi yang Anda, dan pengguna kelas Anda harus waspada daripada yang diperlukan jika Anda menggunakan pola strategi.
Akhirnya, karena kode sampel Anda tidak menunjukkan contoh bagaimana Anda akan mengganti metode 'dukun' dan 'terbang', Anda tidak memperhatikan manfaat besar menggunakan pola strategi - mengurangi duplikasi kode. Apa yang akan Anda lakukan dengan memberikan selusin kelas bebek berbeda yang di antara mereka memiliki 3 perilaku 'terbang' yang berbeda? Dengan menggunakan pendekatan Anda, Anda mungkin menemukan diri Anda memotong dan menempel, dan kemudian mungkin mengekstrak kode duplikat ke dalam kelas 'pembantu' statis. Pola strateginya jauh lebih bersih.
sumber
Demo visual yang bagus selalu bernilai ribuan kata.
John Lindquist melakukan pekerjaan yang baik untuk merekam screencasts tentang pola Desain yang berbeda. Anda dapat menemukan 50 sen tentang pola khusus ini (dan banyak lagi) di blognya
sumber