About Me

header ads

Factory Method Pattern

Bao nhiêu bạn đã từng chơi game phi thuyền bắn súng? Giơ tay lên đi đừng ngại ngần. Có bạn nào chưa chơi game phi thuyền bắn súng không? Nếu chưa chơi thì nói thật, tuổi thơ bạn bất hạnh ghê gớm. Vì sao? vì trò chơi này là cả một tuổi thơ dữ dội, nó là cả 1 tinh hoa của nghệ thuật bắn súng trong đó. Vậy nên, chưa chơi thì hãy đi chơi đi, chơi ngay đi, vì trong bài này, mình sẽ lấy game đó làm ví dụ đấy. =))
Okie, trờ lại với bài này. Nếu như các bạn chơi game phi thuyền bắn súng thì các bạn sẽ thấy, trò chơi có các mảnh thiên thạch to nhỏ khác nhau, xuất hiện liên tục, nhiệm vụ của bạn là lo bắn phá hết tất cả cái đống đó. Vậy để generate ra được cái đống thiên thạch đó thì như nào. I zì, bạn dùng strategy pattern như trong đã học ở bài này rồi thiết kế ra thôi là được.
Giả sử bạn có thiên thạch to, thiên thạch nhỏ, thiên thạch vừa. Mỗi thiên thạch có tốc độ bay khác nhau, có lượng máu khác nhau, thì các bạn có thể dễ cmn dàng áp dụng strategy pattern để thiết kế.
Tất nhiên, bạn có thể tạo interface cho speed và healthy, nhưng ở đây mình tối giản nó lại, vì chúng ta đang học factory chứ ko phải strategy. Okie! Nói chung bạn cứ tạm hiểu là cái chúng ta đang thiết kế mấy viên thiên thạch rất hợp lý vào logic rồi.
Tiếp! Bây giờ làm thế nào để ta tạo ra mấy viên thiên thạch này bay lung tung xì phèo như game đây? Không lẽ cứ khởi tạo từng viên thiên thạch rồi ném nó vào UI à? Nghe như cứt ấy nhỉ? Vậy nên, người ta mới tạo ra ý tưởng là: "À, mình phải tạo 1 lớp, có nhiệm vụ sản sinh ra mấy cái IEnemy. IEnemy này có thể là thiên thạch to, thiên thạch nhỏ, thiên thạch vừa. Chỉ cần ta truyền parameter vào cho nó là nó sẽ tự động trả về cho mình 1 viên thiên thạch." . Ố dè, và đây chính là Factory Pattern.
Có thể hiểu ở đây, Factory là 1 cái nhà máy dùng để sản xuất IEnemy, dựa vào tên của enemy bạn muốn tạo. Và cái thể loại này ấy, người ta gọi là Simple Factory Pattern. Nhiều người cho rằng đây ko phải là pattern, ok thôi, vì mình là thằng ko thích định nghĩa nên người ta muốn bàn gì thì bàn, quan trọng là mình hiểu nó là cái gì là được rồi.
Ok! nhìn chung có vẻ ổn đúng không? Vậy tại sao người ta lại sản sinh ra thêm cái Factory Method Pattern làm gì? Sao không xài Simple Factory Pattern cho rồi, nhìn cũng ngon mà. Hờ, vấn đề là ở đây: chả có cái game củ chuối nào mà cứ bắn hoài mấy cái thiên thạch từ đầu tới cuối cả. Bạn chơi 1 hồi, tất nhiên độ khó của game sẽ tăng dần, mà độ khó game tăng tức là enemy cũng phải tăng dần. Ví dụ bạn chơi được 100 điểm, game sẽ chuyển qua level 2, chơi được 200 điểm game sẽ chuyển qua level 3. Và khi qua level 2 , level 3, game sẽ không còn là bắn thiên thạch nữa, mà chúng ta sẽ phải bắn tàu chiến, bắn rocket chẳng hạn. Vậy để giải quyết cái này thì làm sao?
Hừm, có thể chúng ta sẽ tạo ra những cái factory mới cho từng level tương ứng. Ví dụ ta có: Factory1 để sản sinh ra enemy của level 1, Factory2 để sản inh ra enemy của level 2... Nhưng nếu có 1000 level thì sao? Có thể nhiều bạn bảo: "Làm cứt gì có game 1000 level". Ôi con xin lạy, ý con chỉ là muốn lấy ví dụ để cho thấy cái vấn đề gặp phải của chúng ta thôi. Là bây giờ chúng ta sẽ có rất nhiều factory, và để đưa ra được enemy cho người chơi bắn, chúng ta phải xử lý để tiếp tục chọn factory tương ứng với level. Như vậy thì không hay. Giờ phải nghĩ ra cách mới thôi... Làm sao nhỉ???
À, đúng rồi!!! Chúng ta sẽ tạo ra 1 cái interface tên là IFactory, và những factory của từng level sẽ là hiện thực của IFactory này. Chúng sẽ có chung cơ chế sản sinh enemy là createEnemy, nhưng sẽ sản sinh ra những nhóm enemy khác nhau. Đấy, bạn bây giờ đã sử dụng Factory Method Pattern rồi đấy.
Factory Method Pattern: định nghĩa ra 1 cái interface cho phép ta khởi tạo 1 đối tượng, NHƯNG! Nó sẽ để cho lớp con của nó quyết định việc tạo ra đối tượng cụ thể. Factory Method Pattern nhường lại quyền khởi tạo cho lớp con của nó
Vậy cấu trúc cơ bản của 1 Factory Method Pattern nó là như nào? Đầu tiên ta sẽ có 1 cái interface product, và những hiện thực của nó.
Sau đó ta có 1 cái interface của Factory và những hiện thực con của nó.
Vậy đấy, Factory Method Pattern là vậy. Okie, chúng ta sẽ thử code 1 cách ngắn gọn xem nó hoạt động như nào nhá.
Đầu tiên là interface Enemy và 2 hiện thực con ở 2 level khác nhau. Chúng ta sẽ phân tầng nó để nhìn code có vẻ đẹp hơ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 IFactory{
public Enemy createEnemy();
}
public class FirstLevelFactory implements IFactory {
public Enemy createEnemy() {
return RandomEnemy();
}
private FirstLevelEnemy RandomEnemy() {
//lam gi do de random cac kieu
}
}
public class SecondLevelFactory implements IFactory {
public Enemy createEnemy() {
return RandomEnemy();
}
private SecondLevelEnemy RandomEnemy() {
//lam gi do de random cac kieu
}
}
Bạn có thể bọc thêm 1 lớp factory bên ngoài IFactory được nữa. Ví dụ:

public class MotherOfFactory {
public static IFactory createFactory(int level) {
switch (level) {
case 1: return FirstLevelFactory(); break;
case 2: return SecondLevelFactory(); break;
//and so on
}
}
}
H bạn muốn tạo enemy của level 1 thì chỉ cần gõ vài dòng.

Enemy enemy = MotherOfFactory.createFactory(1).createEnemy();
H bạn muốn tạo enemy của level 2 thì chỉ cần gõ:

Enemy enemy = MotherOfFactory.createFactory(2).createEnemy();

Đăng nhận xét

0 Nhận xét