Hai! Hari ini kita akan terus mengkaji corak reka bentuk dan kita akan membincangkan corak kaedah kilang.
Anda akan mengetahui apakah itu dan tugas apa yang sesuai untuk corak ini. Kami akan mempertimbangkan corak reka bentuk ini dalam amalan dan mengkaji strukturnya. Untuk memastikan semuanya jelas, anda perlu memahami topik berikut:
Apakah kesimpulan yang boleh kita buat?
Rajah di atas menunjukkan struktur umum corak kaedah kilang. Apa lagi yang penting di sini?

- Warisan di Jawa.
- Kaedah dan kelas abstrak di Jawa
Apakah masalah yang diselesaikan oleh kaedah kilang?
Semua corak reka bentuk kilang mempunyai dua jenis peserta: pencipta (kilang itu sendiri) dan produk (objek yang dicipta oleh kilang). Bayangkan situasi berikut: kami mempunyai kilang yang mengeluarkan kereta berjenama CodeGym. Ia tahu cara mencipta model kereta dengan pelbagai jenis badan:- kereta sedan
- gerabak stesen
- coupe
- kereta sedan CodeGym
- gerabak stesen CodeGym
- CodeGym coupes
- kereta sedan OneAuto
- Gerabak stesen OneAuto
- OneAuto coupe
Sedikit tentang corak kilang
Izinkan saya mengingatkan anda bahawa sebelum ini kami telah membina sebuah kedai kopi maya kecil. Dengan bantuan kilang yang ringkas, kami belajar cara mencipta pelbagai jenis kopi. Hari ini kita akan mengolah semula contoh ini. Mari kita ingat bagaimana rupa kedai kopi kami, dengan kilangnya yang ringkas. Kami mempunyai kelas kopi:
public class Coffee {
public void grindCoffee(){
// Grind the coffee
}
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
Dan beberapa kelas kanak-kanak yang sepadan dengan jenis kopi tertentu yang boleh dihasilkan oleh kilang kami:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Kami mencipta enum untuk memudahkan anda membuat pesanan:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
Kilang kopi itu sendiri kelihatan seperti ini:
public class SimpleCoffeeFactory {
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappuccino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
return coffee;
}
}
Dan akhirnya, kedai kopi itu sendiri kelihatan seperti ini:
public class CoffeeShop {
private final SimpleCoffeeFactory coffeeFactory;
public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
}
Memodenkan kilang yang ringkas
Kedai kopi kami berjalan dengan baik. Sehinggakan kami sedang mempertimbangkan untuk berkembang. Kami ingin membuka beberapa lokasi baharu. Kami berani dan berdaya usaha, jadi kami tidak akan membuka kedai kopi yang membosankan. Kami mahu setiap kedai mempunyai kelainan yang istimewa. Sehubungan itu, sebagai permulaan, kami akan membuka dua lokasi: satu Itali dan satu Amerika. Perubahan ini akan menjejaskan bukan sahaja reka bentuk dalaman, tetapi juga minuman yang ditawarkan:- di kedai kopi Itali, kami akan menggunakan jenama kopi Itali secara eksklusif, dengan pengisaran dan pemanggangan khas.
- lokasi Amerika akan mempunyai bahagian yang lebih besar, dan kami akan menyediakan marshmallow dengan setiap pesanan.
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Tetapi sekarang kita akan mempunyai 8:
public class ItalianStyleAmericano extends Coffee {}
public class ItalianStyleCappucino extends Coffee {}
public class ItalianStyleCaffeLatte extends Coffee {}
public class ItalianStyleEspresso extends Coffee {}
public class AmericanStyleAmericano extends Coffee {}
public class AmericanStyleCappucino extends Coffee {}
public class AmericanStyleCaffeLatte extends Coffee {}
public class AmericanStyleEspresso extends Coffee {}
Memandangkan kami ingin mengekalkan model perniagaan semasa, kami mahu orderCoffee(CoffeeType type)
kaedah itu mengalami sedikit perubahan yang mungkin. Lihatlah ia:
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
Apakah pilihan yang kita ada? Nah, kita sudah tahu cara menulis kilang, bukan? Perkara paling mudah yang segera terlintas di fikiran ialah menulis dua kilang yang serupa, dan kemudian menyerahkan pelaksanaan yang dikehendaki kepada pembina kedai kopi kami. Dengan melakukan ini, kelas kedai kopi tidak akan berubah. Mula-mula, kita perlu mencipta kelas kilang baharu, menjadikannya mewarisi kilang ringkas kami, dan kemudian mengatasi createCoffee(CoffeeType type)
kaedah tersebut. Mari kita tulis kilang untuk mencipta kopi gaya Itali dan kopi gaya Amerika:
public class SimpleItalianCoffeeFactory extends SimpleCoffeeFactory {
@Override
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new ItalianStyleAmericano();
break;
case ESPRESSO:
coffee = new ItalianStyleEspresso();
break;
case CAPPUCCINO:
coffee = new ItalianStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new ItalianStyleCaffeLatte();
break;
}
return coffee;
}
}
public class SimpleAmericanCoffeeFactory extends SimpleCoffeeFactory{
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new AmericanStyleAmericano();
break;
case ESPRESSO:
coffee = new AmericanStyleEspresso();
break;
case CAPPUCCINO:
coffee = new AmericanStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new AmericanStyleCaffeLatte();
break;
}
return coffee;
}
}
Kini kita boleh menghantar pelaksanaan kilang yang dikehendaki kepada CoffeeShop. Mari lihat rupa kod untuk memesan kopi dari kedai kopi yang berbeza. Contohnya, cappucino gaya Itali dan gaya Amerika:
public class Main {
public static void main(String[] args) {
/*
Order an Italian-style cappuccino:
1. Create a factory for making Italian coffee
2. Create a new coffee shop, passing the Italian coffee factory to it through the constructor
3. Order our coffee
*/
SimpleItalianCoffeeFactory italianCoffeeFactory = new SimpleItalianCoffeeFactory();
CoffeeShop italianCoffeeShop = new CoffeeShop(italianCoffeeFactory);
italianCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
/*
Order an American-style cappuccino
1. Create a factory for making American coffee
2. Create a new coffee shop, passing the American coffee factory to it through the constructor
3. Order our coffee
*/
SimpleAmericanCoffeeFactory americanCoffeeFactory = new SimpleAmericanCoffeeFactory();
CoffeeShop americanCoffeeShop = new CoffeeShop(americanCoffeeFactory);
americanCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
}
}
Kami mencipta dua kedai kopi yang berbeza, memberikan kilang yang dikehendaki kepada setiap kedai. Di satu pihak, kami telah mencapai objektif kami, tetapi di sisi lain... Entah bagaimana ini tidak sesuai dengan usahawan... Mari kita fikirkan apa yang salah. Pertama, kelimpahan kilang. Apa? Sekarang untuk setiap lokasi baharu, kami sepatutnya mencipta kilangnya sendiri dan, sebagai tambahan kepada itu, pastikan kilang yang berkaitan diserahkan kepada pembina semasa membuat kedai kopi? Kedua, ia masih kilang yang ringkas. Baru dimodenkan sedikit. Tetapi kami di sini untuk mempelajari corak baharu. Ketiga, bukankah pendekatan yang berbeza mungkin? Alangkah baiknya jika kita boleh meletakkan semua isu yang berkaitan dengan penyediaan kopi ke dalamCoffeeShop
kelas dengan menghubungkan proses mencipta kopi dan melayan pesanan, pada masa yang sama mengekalkan fleksibiliti yang mencukupi untuk membuat pelbagai gaya kopi. Jawapannya ya, kita boleh. Ini dipanggil corak reka bentuk kaedah kilang.
Dari kilang yang mudah kepada kaedah kilang
Untuk menyelesaikan tugasan secekap mungkin:- Kami mengembalikan
createCoffee(CoffeeType type)
kaedah keCoffeeShop
kelas. - Kami akan menjadikan kaedah ini abstrak.
- Kelas
CoffeeShop
itu sendiri akan menjadi abstrak. - Kelas
CoffeeShop
akan mempunyai kelas kanak-kanak.
CoffeeShop
, yang melaksanakan createCoffee(CoffeeType type)
kaedah mengikut tradisi terbaik barista Itali. Sekarang, satu langkah pada satu masa. Langkah 1. Jadikan Coffee
kelas abstrak. Kami mempunyai dua keluarga keseluruhan produk yang berbeza. Namun, kopi Itali dan Amerika mempunyai nenek moyang yang sama - kelasnya Coffee
. Adalah wajar untuk menjadikannya abstrak:
public abstract class Coffee {
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
Langkah 2. Buat abstrak, dengan kaedah CoffeeShop
abstrakcreateCoffee(CoffeeType type)
public abstract class CoffeeShop {
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = createCoffee(type);
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
protected abstract Coffee createCoffee(CoffeeType type);
}
Langkah 3. Buat kedai kopi Itali, yang merupakan keturunan kedai kopi abstrak. Kami melaksanakan createCoffee(CoffeeType type)
kaedah di dalamnya, dengan mengambil kira spesifik resipi Itali.
public class ItalianCoffeeShop extends CoffeeShop {
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new ItalianStyleAmericano();
break;
case ESPRESSO:
coffee = new ItalianStyleEspresso();
break;
case CAPPUCCINO:
coffee = new ItalianStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new ItalianStyleCaffeLatte();
break;
}
return coffee;
}
}
Langkah 4. Kami melakukan perkara yang sama untuk kedai kopi gaya Amerika
public class AmericanCoffeeShop extends CoffeeShop {
@Override
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new AmericanStyleAmericano();
break;
case ESPRESSO:
coffee = new AmericanStyleEspresso();
break;
case CAPPUCCINO:
coffee = new AmericanStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new AmericanStyleCaffeLatte();
break;
}
return coffee;
}
}
Langkah 5. Lihat bagaimana latte Amerika dan Itali akan kelihatan:
public class Main {
public static void main(String[] args) {
CoffeeShop italianCoffeeShop = new ItalianCoffeeShop();
italianCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
CoffeeShop americanCoffeeShop = new AmericanCoffeeShop();
americanCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
}
}
tahniah. Kami hanya melaksanakan corak reka bentuk kaedah kilang menggunakan kedai kopi kami sebagai contoh.
Prinsip di sebalik kaedah kilang
Sekarang mari kita pertimbangkan dengan lebih terperinci apa yang kita dapat. Rajah di bawah menunjukkan kelas yang terhasil. Blok hijau ialah kelas pencipta, dan blok biru ialah kelas produk.
- Semua produk adalah pelaksanaan
Coffee
kelas abstrak. - Semua pencipta adalah pelaksanaan
CoffeeShop
kelas abstrak. - Kami melihat dua hierarki kelas selari:
- Hierarki produk. Kami melihat keturunan Itali dan keturunan Amerika
- Hierarki pencipta. Kami melihat keturunan Itali dan keturunan Amerika
- Superclass
CoffeeShop
tidak mempunyai maklumat tentang produk tertentu (Coffee
) yang akan dibuat. - Kelas
CoffeeShop
super mewakilkan penciptaan produk tertentu kepada keturunannya. - Setiap keturunan
CoffeeShop
kelas melaksanakancreateCoffee()
kaedah kilang mengikut ciri khususnya sendiri. Dengan kata lain, pelaksanaan kelas pengeluar menyediakan produk khusus berdasarkan spesifikasi kelas pengeluar.
Struktur kaedah kilang

- Kelas Pencipta melaksanakan semua kaedah yang berinteraksi dengan produk, kecuali kaedah kilang.
- Kaedah abstrak
factoryMethod()
mesti dilaksanakan oleh semua keturunan kelasCreator
. - Kelas
ConcreteCreator
melaksanakanfactoryMethod()
kaedah, yang secara langsung mencipta produk. - Kelas ini bertanggungjawab untuk mencipta produk tertentu. Ini adalah satu-satunya kelas dengan maklumat tentang mencipta produk ini.
- Semua produk mesti melaksanakan antara muka biasa, iaitu mereka mestilah keturunan kelas produk biasa. Ini adalah perlu supaya kelas yang menggunakan produk boleh beroperasi pada mereka sebagai abstraksi, bukannya pelaksanaan khusus.
GO TO FULL VERSION