Abstract Factory Pattern: cung cấp 1 interface cho phép người dùng tạo ra 1 nhóm các đối tượng độc lập hoặc có liên hệ với nhau mà không cần quan tâm tới lớp thực thi của chúng
Nghe có vẻ bù cả đầu đúng không? Nhưng mà sự thật thì cực kì đơn giản. Quay lại với ví dụ trong bài Factory Method Pattern, chúng ta có cái game phi thuyền bắn súng đấy. Bạn để ý nhé, trong game lúc nào cũng có background (tức là cái hình nền ấy) nó xuất hiện khác nhau với mỗi level. Ví dụ với level 1, mục tiêu là bắn các mảnh thiên thạch thì background sẽ là bầu trời đêm chẳng hạn. Level 2 bắn phá các phi thuyền thì background sẽ là các linh kiện máy móc... vân vân và mây mây. Và tất nhiên, không phải background của chúng ta là random được, nó phải có lý với bối cảnh của enemy. Không phải tự dưng enemy là các mảnh thiên thạch, mà background lại là đồng cỏ được, nó không có phù hợp gì hết. Hay là enemy là mấy con bò, mà background lại là trên dải ngân hà, đúng lafk hông hợp lý. Vậy nên, ứng với mỗi enemy, chúng ta phải có 1 background đi kèm. Vậy để làm được thế thì ta không thể tạo 2 cái Factory riêng biệt cho enemy và background được. Vì có thể, trong tương lai, không những chỉ có background mà có thể có các hiệu ứng mây mưa, sương khói các thứ cũng phải làm sao cho hợp lý. Như vậy sẽ dẫn tới chúng ta có vô vàn Factory riêng lẻ. Và Abstract Factory Pattern lúc này mới được đưa vào sử dụng.
Cùng xem lại mô hình củ Factory Method Pattern nhé.
Ta thấy, mỗi factory sẽ tạo cho chúng ta 1 đối tượng là IProduct. Nhưng ở bài toán hiện tại, chúng ta không chỉ có 1 product (là enemy) nữa, mà chúng ta có đến 2, hoặc 3 đối tượng cơ. Vậy nên, Abstract Factory Pattern cải tiến lại, giúp cho Factory có thể cho ra được 2 nhiều hơn 1 product.
Ví dụ ta có 2 interface IProductEnemy và IProductBackground, mô hình cảu Abstract Factory Pattern sẽ như sau: Ta thấy, bây h factory của chúng ta đã có thể cho ra 2 product. Và tất nhiên, khi hiện thực IFactory, thì chúng ta cũng đã định nghĩa được những background nào nên đi kèm với enemy nào rồi, nên sẽ ko có hiện tượng bất hợp lý ở UI khi người ta chơi game cả. Vậy thôi, đó là Abstract Factory Pattern.
Bây h thử code vài dòng để hiểu hơn nó là như thế nào nà. Đầu tiên vẫn như cũ, ta tạo interface của enemy và các hiện thực của nó.
Bây giờ chúng ta tạo ra interface cho background và các hiện thực của nó.
public interface Enemy{
public void speed();
public void healthy();
}
public interface FirstLevelEnemy extends Enemy{
}
public interface SecondLevelEnemy extends Enemy{
}
public class BigMeteorite implements FirstLevelEmemy {
public void speed() {
//lam cai gi do
}
public void healthy(){
//lam cai gi do
}
}
public class VietNamSpaceShip implements SecondLevelEnemy {
public void speed() {
//lam cai gi do
}
public void healthy(){
//lam cai gi do
}
}
Tiếp đến ta tạo ra interface Factory và các hiện thực của nó.
public interface Background{
public void display();
}
public interface FirstLevelBackground extends Background{
}
public interface SecondLevelBackground extends Background{
}
public class DarkGalaxy implements FirstLevelBackground {
public void display() {
//lam cai gi do
}
}
public class OldShipFLoor implements SecondLevelBackground {
public void display() {
//lam cai gi do
}
}
Và cuối cùng là thêm 1 lớp factory bên ngoài IFactory được nữa. Ví dụ:
public interface IFactory{
public Enemy createEnemy();
public Background createBackground();
}
public class FirstLevelFactory implements IFactory {
public Enemy createEnemy() {
return RandomEnemy();
}
public Background createBackground() {
return RandomEnemy();
}
private FirstLevelEnemy RandomEnemy() {
//lam gi do de random cac kieu
}
private FirstLevelBackground RandomBackground() {
//lam gi do de random cac kieu
}
}
public class SecondLevelFactory implements IFactory {
public Enemy createEnemy() {
return RandomEnemy();
}
public Background createBackground() {
return RandomEnemy();
}
private SecondLevelEnemy RandomEnemy() {
//lam gi do de random cac kieu
}
private SecondLevelBackground RandomBackground() {
//lam gi do de random cac kieu
}
}
Bây giờ giả sử bạn ở level 1, thì có thể khởi tạo enemy bằng cách.
public class MotherOfFactory {
public static IFactory createFactory(int level) {
switch (level) {
case 1: return FirstLevelFactory(); break;
case 2: return SecondLevelFactory(); break;
//and so on
}
}
}
Nếu bây giờ, bạn muốn lấy background, thì chỉ cần:
Enemy enemy = MotherOfFactory.createFactory(1).createEnemy();
Lúc này Background và Enemy của bạn sẽ rất hợp lý, vì bạn đã định nghĩa nó ngay trong hiện thực của IFactory rồi.
Background background = MotherOfFactory.createFactory(1).createBackground();
Vậy thôi, quá đơn giản phải không?
0 Nhận xét