Chào bạn! Hôm nay chúng ta sẽ tiếp tục cùng các bạn nghiên cứu các mẫu thiết kế. Trong bài giảng này chúng ta sẽ nói về Nhà máy. Chúng tôi sẽ thảo luận với bạn vấn đề nào được giải quyết bằng cách sử dụng mẫu này và xem ví dụ về cách một nhà máy giúp mở quán cà phê. Và tôi cũng sẽ cung cấp cho bạn 5 bước đơn giản để tạo nhà máy. Để cùng quan điểm với mọi người và dễ dàng nắm bắt được bản chất, bạn nên làm quen với các chủ đề sau:
- Kế thừa trong Java
- Thu hẹp và mở rộng các loại tham chiếu trong Java
- Tương tác giữa các lớp và đối tượng khác nhau
Nhà máy là gì?
Mẫu thiết kế Factory cho phép bạn kiểm soát việc tạo đối tượng. Quá trình tạo một đối tượng mới không đơn giản nhưng cũng không quá phức tạp. Chúng ta đều biết rằng để tạo một đối tượng mới, chúng ta phải sử dụng lớpnew
. Và có vẻ như không có gì phải quản lý ở đây, nhưng thực tế không phải vậy. Khó khăn có thể nảy sinh khi ứng dụng của chúng ta có một lớp nhất định có nhiều lớp con và cần phải tạo một thể hiện của một lớp nhất định tùy thuộc vào một số điều kiện. Factory là một mẫu thiết kế giúp giải quyết vấn đề tạo ra các đối tượng khác nhau tùy theo một số điều kiện. Trừu tượng phải không? Tính cụ thể và rõ ràng hơn sẽ xuất hiện khi chúng ta xem ví dụ bên dưới.
Chúng tôi tạo ra nhiều loại cà phê khác nhau
Giả sử chúng ta muốn tự động hóa một quán cà phê. Chúng ta cần học cách pha chế các loại cà phê khác nhau. Để làm điều này, trong ứng dụng của chúng tôi, chúng tôi sẽ tạo một loại cà phê và các dẫn xuất của nó: Americano, cappuccino, espresso, latte - những loại cà phê mà chúng tôi sẽ pha chế. Hãy bắt đầu với lớp cà phê chung:public class Coffee {
public void grindCoffee(){
// перемалываем кофе
}
public void makeCoffee(){
// делаем кофе
}
public void pourIntoCup(){
// наливаем в чашку
}
}
Tiếp theo, hãy tạo những người thừa kế của nó:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Khách hàng của chúng tôi sẽ gọi một số loại cà phê và thông tin này cần được chuyển đến chương trình. Điều này có thể được thực hiện theo nhiều cách khác nhau, ví dụ như sử dụng String
. Nhưng nó phù hợp nhất cho những mục đích này enum
. Hãy tạo enum
và xác định trong đó các loại cà phê mà chúng tôi nhận đặt hàng:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
Tuyệt vời, bây giờ hãy viết mã cho quán cà phê của chúng ta:
public class CoffeeShop {
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappucсino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
}
Phương pháp này orderCoffee
có thể được chia thành hai thành phần:
switch-case
Tạo một thể hiện cà phê cụ thể trong một khối Đây là nơi mà Nhà máy thực hiện việc tạo ra một loại cụ thể tùy thuộc vào các điều kiện.- Bản thân việc chuẩn bị là xay, nấu và đổ vào cốc.
- Bản thân thuật toán chuẩn bị (nghiền, nấu và rót vào cốc) sẽ không thay đổi (ít nhất là chúng tôi hy vọng như vậy).
- Nhưng phạm vi cà phê có thể thay đổi. Có lẽ chúng ta sẽ bắt đầu làm mocha.. Mocha.. Mokkachi... Chúa phù hộ cho anh ấy, một loại cà phê mới.
switch-case
. Cũng có thể trong quán cà phê của chúng tôi, phương pháp này orderCoffee
sẽ không phải là nơi duy nhất chúng tôi tạo ra các loại cà phê khác nhau. Vì vậy, những thay đổi sẽ phải được thực hiện ở một số nơi. Có lẽ bạn đã hiểu điều tôi đang muốn nói. Chúng ta cần tái cấu trúc. Di chuyển khối chịu trách nhiệm tạo cà phê vào một lớp riêng vì hai lý do:
- Chúng tôi sẽ có thể sử dụng lại logic tạo cà phê ở những nơi khác.
- Nếu phạm vi thay đổi, chúng tôi sẽ không phải chỉnh sửa mã ở mọi nơi sẽ sử dụng tính năng tạo cà phê. Chỉ cần thay đổi mã ở một nơi là đủ.
Chúng tôi đang cưa nhà máy đầu tiên của mình
Để làm điều này, hãy tạo một lớp mới sẽ chỉ chịu trách nhiệm tạo các phiên bản cần thiết của các lớp cà phê: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 Cappucino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
return coffee;
}
}
Chúc mừng! Chúng ta vừa triển khai mẫu thiết kế Factory ở dạng đơn giản nhất. Mặc dù mọi thứ có thể còn đơn giản hơn nếu phương thức được đặt ở createCoffee
dạng tĩnh. Nhưng khi đó chúng ta sẽ mất đi hai khả năng:
- Kế thừa
SimpleCoffeeFactory
và ghi đècreateCoffee
. - Triển khai việc triển khai nhà máy được yêu cầu trong các lớp học của chúng tôi.
Đưa nhà máy vào quán cà phê
Hãy viết lại lớp quán cà phê của chúng ta bằng cách sử dụng một nhà máy: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("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
}
Tuyệt vời. Bây giờ chúng ta hãy thử mô tả sơ đồ và chính xác cấu trúc của mẫu thiết kế Factory.
5 bước để mở nhà máy của riêng bạn
Bước 1. Trong chương trình của bạn, bạn có một lớp với một số lớp con, như trong hình bên dưới: Bước 2. Bạn tạo một lớpenum
trong đó bạn xác định một biến enum cho mỗi lớp con:
enum CatType {
LION,
TIGER,
BARSIK
}
Bước 3. Bạn xây dựng nhà máy của mình. Bạn gọi nó MyClassFactory
, mã dưới đây:
class CatFactory {}
Bước 4. Bạn tạo một phương thức trong nhà máy của mình createMyClass
có biến - enum
MyClassType
. Mã dưới đây:
class CatFactory {
public Cat createCat(CatType type) {
}
}
Bước 5. Bạn viết một khối trong phần thân của phương thức switch-case
để lặp qua tất cả các giá trị enum và tạo một thể hiện của lớp tương ứng với enum
giá trị đó:
class CatFactory {
public Cat createCat(CatType type) {
Cat cat = null;
switch (type) {
case LION:
cat = new Barsik();
break;
case TIGER:
cat = new Tiger();
break;
case BARSIK:
cat = new Lion();
break;
}
return cat;
}
}
Giống như một ông chủ.
GO TO FULL VERSION