Báo cáo cuối kỳ môn Lập trình hướng đối tượng - Chủ đề: Strategy Pattern - Nguyễn Hoàng Thức
ĐẠI HỌC QUỐC GIA THÀNH PHỐ HỒ CHÍ MINH
TRƯỜNG ĐẠI HỌC KHOA HỌC TỰ NHIÊN
Khoa Công nghệ Thông tin
BÁO CÁO CUỐI KÌ
Môn: Lập trình hướng đối tượng
Chủ đề: Strategy Pattern
Nhóm: 3
Sinh viên thực hiện :
1760438 : Nguyễn Hoàng Thức
1760311 : Hoàng Minh Hiếu
1760479 : Phạm Hữu Tài
1760332 : Nguyễn Quốc Khánh
TP.HCM, ngày 25 tháng 11 năm 2018
Mục lục
I. Bài toán sử dụng Strategy Pattern:..............................................................................2
II. Cách giải bài toán nếu không sử dụng pattern:...........................................................2
III. Nhược điểm của cách giải ở trên : ...............................................................................3
IV. Giới thiệu về Strategy Pattern ......................................................................................4
i.
ii.
Khái niệm:............................................................................................................................4
Mục đích...............................................................................................................................4
Trường hợp nào nên sử dụng Strategy Pattern? .................................................................4
iii.
V. Cách giải bài toán trên nếu sử dụng pattern: ..............................................................4
VI. Một số bài toán khác có thể giải bằng Strategy Pattern...............................................6
VII.Ưu và nhược điểm........................................................................................................6
i.
Ưu điểm: ..............................................................................................................................6
Nhược điểm :........................................................................................................................6
ii.
I. Bài toán sử dụng Strategy Pattern
Bài toán:
Giả sử chúng ta sẽ xây dựng một game tên là Street Fighter. Game sẽ có các nhân vật
(Character). Mỗi nhân vật có 4 kĩ năng là đá (kick), đấm (punch), lăn (roll) và nhảy (jump). Mỗi
nhân vật đều có 2 kĩ năng cơ bản là punch() và roll(), còn 2 kĩ năng còn lại là kick() và jump()
thì sẽ phụ thuộc vào mỗi nhân vật. Ngoài ra, 2 kĩ năng đó còn có nhiều cách thực hiện.
Hãy xây dựng các lớp trên bằng phương pháp lập trình hướng đối tượng bằng ý tưởng sử dụng
kế thừa và đa hình.
II. Cách giải bài toán nếu không sử dụng pattern
Vài toán này, ta dùng tính kế thừa (Inheritance) để xây dựng các lớp.
Ta gọi class Fighter là class tổng quát của game. Lớp Fighter sẽ có những default
implementation của các hành động. Mỗi nhân vật nếu có những hành động đặc biệt đều có thể
override lại các actions cơ bản. Ví dụ LeeSin có thể override lại method Kick() bằng
DragonKick() (Nộ long cước).
Do đó ta có sơ đồ UML sử dụng đa hình như sau :
Fighter class
+ Display(): void
+ Kick(): void
+ Punch(): void
+ Jump: void
+ Roll: void
LeeSin
Garen
Gragas
+ Display(): void
+ Kick(): void
+ Display(): void
+ Kick(): void
+ Display(): void
+ Kick(): void
+ Punch(): void
+ Jump: void
+ Punch(): void
+ Roll: void
+ Punch(): void
+ ShortJump: void
+ Roll(): void
+ LongJump():void
+ LightningKick(): void
Theo UML trên, ta có các class con kế thừa đủ các action cơ bản.
Trong trường hợp nhân vật nào không có những action đặc biệt, ta sẽ override nó thành một
method rỗng. Ví dụ Garen không có action Roll, do đó ta sẽ implement lại method Roll() bằng
cách override lại.
cl ass Gar en : publ i c Fi ght er
{
publ i c:
voi d Ki ck( ) {
}
} ;
Như vậy, cơ bản lớp Fighter đã được hoàn thành, và có thể chạy được.
WithoutStrategy.cp
p
Source code đính kèm (nhấn đúp để mở):
III. Nhược điểm của cách giải ở trên
Theo cách làm trên, chuyện gì sẽ xảy ra nếu như có 1 nhân vật nào đó không có hành động
đặc biệt, như Roll() (lăn) chả hạn?
Mặc dù chúng ta có thể override hành động Roll() thành một method rỗng như hình trên,
nhưng giả sử nếu game có tới bao nhiêu nhân vật tương tự như vậy, ta phải override lại
method Roll() bấy nhiêu lần, chưa kể nếu sau này game có thể ra thêm nhiều nhân vật khác
cũng không có hành động Roll(). Nếu như ta quên không override, các kĩ năng sẽ bị leak và các
nhân vật sẽ có đầy đủ các kĩ năng như bình thường.
Do đó, sử dụng kế thừa (Inheritance) cho bài toán này sẽ gây khó khăn cho việc maintain cũng
như là develop.
IV. Giới thiệu về Strategy Pattern
Khái niệm:
Strategy Pattern (thuộc nhóm Behavior Pattern) là một mẫu thiết kế cho phép phương thức của
đối tượng được chọn khi chạy chương trình.
Mục đích
Định nghĩa và bao bọc các thuật toán có cùng mục đích trong những lớp có giao diện chung.
Làm cho sự thay đổi thuật toán trở lên linh động và độc lập với khách hàng, cho phép giải thuật
tùy biến độc lập tại Client sử dụng nó.
Strategy thường được sử dụng để thay thế cho sự kế thừa, khi bạn muốn chấm dứt việc theo
dõi và chỉnh sửa 1 chức năng qua nhiều lớp con.
Trường hợp nào nên sử dụng Strategy Pattern?
Đoạn code dễ thay đổi và muốn tách chúng ra khỏi chương trình chính để dễ dàng chỉnh sửa,
bảo trì.
Tránh sự rắc rối khi phải hiện thực một chức năng nào đó qua quá nhiều lớp con.
Muốn thay đổi thuật toán sử dụng khi chạy chương trình.
V. Cách giải bài toán trên nếu sử dụng pattern
Pattern ta sử dụng để giải quyết bài toán này sẽ là Strategy.
Các bước thực hiện ý tưởng và xây dựng các class:
Bước đầu tiên ta sẽ nhận diện các hành động nào có thể được tái sử dụng và có nhiều biến thể,
phân tách nó thành những class riêng biệt.
Ở đây các hành động đó là Kick() va Jump(). Ta đưa 2 method ra khỏi class Fighter và tạo mỗi
class đại diện cho mỗi hành động.
Class diagram hoàn chỉnh:
KickBehavior
Kick(): void
Fighter
- Kick behavior: KickBehavior
- JumpBehavior: JumpBehavior
LightningKick
Kick(): void
DragonKick
Kick(): void
+ Display(): void
+ Kick(): void
+Jump(): void
+ Punch(): void
+ setKickBehavior(): void
+ setJumpBehavior(): void
JumpBehavior
Jump(): void
LongJump
ShortJump
Jump(): void
Jump(): void
LeeSin
Gragas
Garen
+ Display(): void
+ Kick(): void
+ Punch(): void
+ Roll: void
+ Display(): void
+ Kick(): void
+ Punch(): void
+ Jump: void
+ Display(): void
+ Punch(): void
+Jump(): void
Như vậy source code cho bài toán này với ý tưởng dùng Strategy ở đây:
UsingStrategy.cpp
Nhận xét : Sử dụng Strategy pattern cho bài toán này giúp ta dễ dàng maintain từ class cao
đến thấp. Giả sử như nếu có một kĩ năng mới tên là BackKick, ta chỉ đơn giản implement
BackKick class kế thừa KickBehavior, rồi setKickBehavior thành BackKick cho nhân vật.
Với những nhân vật không có kĩ năng kick, ta cũng đơn giản tạo 1 class DisableKick kế thừa
KickBehavior, rồi setKickBehavior cho những nhân vật đó.
Và hơn thế, ta có thể cất giữ 2 kĩ năng Kick và Jump với private access , giúp các nhân vật tạo
ra không đơn giản kế thừa được những kĩ năng này. Mà do chính chúng ta sẽ quyết định nhân
vật tạo ra có quyền thực hiện kiểu kick, kiểu jump nào hoặc không có cả 2 kĩ năng.
VI. Một số bài toán khác có thể giải bằng Strategy Pattern
Ví dụ: 1. Trong nông trại có nhiều vật nuôi, mỗi vật nuôi có những
phương thức ăn cỏ, cho sữa, sinh con khác nhau. Cài đặt phương thức đó cho class Giasuc để
chúng thực hiện đúng với mỗi loài.
2. Các phương tiện di chuyển như xe đạp, máy bay, xe hơi, tàu ngầm…
có phương thức “go” khác nhau. Cài đặt chương trình để con người sử dụng phương tiện với
phương thức “go” chính xác cho mỗi phương tiện.
VII. Ưu và nhược điểm
Ưu điểm:
Một nhóm các thuật toán có thể được định nghĩa như một hệ thống phân cấp lớp và có thể
được sử dụng thay thế cho nhau để thay đổi hành vi, ứng dụng mà không thay đổi kiến trúc
của nó.
Bằng cách đóng gói thuật toán một cách riêng biệt, các thuật toán mới tuân thủ cùng một giao
diện có thể dễ dàng được giới thiệu.
Ứng dụng có thể chuyển đổi chiến lược trong lúc chạy chương trình.
Strategy cho phép người dùng lựa chọn thuật toán cần thiết mà không cần sử dụng câu lệnh
“switch” hoặc một loạt câu lệnh “if - else”.
Các cấu trúc dữ liệu được sử dụng để thực hiện thuật toán được đóng gói hoàn toàn trong các
Strategy class. Do đó, việc thực hiện một thuật toán có thể được thay đổi mà không ảnh hưởng
đến Context class.
Nhược điểm :
Các ứng dụng phải được biết tất cả các thuật toán đã cài đặt để chọn một trong những thuật
toán trong tình huống thích hợp.
Context và các Strategy class thường giao tiếp thông qua giao diện được chỉ định bởi abstract
Strategy base class. Strategy base class phải trưng ra giao diện cho tất cả các hành vi cần thiết,
mà một số lớp chiến lược cụ thể có thể không triển khai.
Trong hầu hết các trường hợp, ứng dụng sẽ cấu hình Context với đối tượng Strategy cần thiết.
Do đó, ứng dụng cần tạo và duy trì hai đối tượng thay cho một đối tượng.
Bạn đang xem tài liệu "Báo cáo cuối kỳ môn Lập trình hướng đối tượng - Chủ đề: Strategy Pattern - Nguyễn Hoàng Thức", để tải tài liệu gốc về máy hãy click vào nút Download ở trên
File đính kèm:
bao_cao_cuoi_ky_mon_lap_trinh_huong_doi_tuong_chu_de_strateg.docx
Decorator.pptx
WithoutStrategy.cpp
UsingStrategy.cpp
Decorater.cpp

