You are on page 1of 23

Nhóm 8

Nguyễn Lê Nguyên Anh 17110094


Lê Hồng Danh 17110108
Ngô Trí Đức 17110127
Lê Quốc Nguyên Vương 17145253

Bài tập nhóm phần Creational Patterns


Factory Method
1. Công dụng chính của mẫu

Được sử dụng để định nghĩa interface tạo ra một object, nhưng chỉ để
subclass quyết định class nào được sử dụng để tạo object theo class đó. Nó có thể
được dùng tạo class interface trước và chỉ rõ class concrete sau.

2. Các trường hợp nào có thể sử dụng mẫu

● Factory Method thường được dùng trong bộ phát triển (toolkit) hay
framework, ở đó đoạn mã của framework cần thiết phải tạo một đối tượng là
những lớp con của ứng dụng sử dụng framework đó.
● Khi bạn muốn có 1 lớp con, mở rộng từ 1 lớp cha, quyết định lại đối tượng
được khởi tạo.
● Khi bạn biết khi nào thì khởi tạo 1 đối tượng nhưng không biết loại đối
tượng nào được khởi tạo.
● Bạn cần một vài khai báo chồng phương thức tạo với danh sách các tham số
như nhau, điều mà Java không cho phép. Thay vì điều đó ta sử dụng các
Factory Method với các tên khác nhau.
3. Các thành phần (lớp) chính của mẫu

Hình 1: Thành phần (lớp) chính của mẫu Factory Method

Các class và object tham gia vào pattern này bao gồm:

● Product (Page): xác định interface của object mà factory method tạo ra

● ConcreteProduct (SkillsPage, EducationPage, ExperiencePage) + các class


implements Product interface

● Creator (Document) + khai báo factory method, trả về 1 object là loại


product cụ thể. Creator có thể là factory method mặc định trả về
ConcreteProduct object mặc định + có thể gọi factory method để tạo ra
Product object

● ConcreteCreator (Report, Resume): override factory method để trả về


instance của ConcreteProduct

4. Những ưu điểm (điểm có lợi) khi sử dụng mẫu.

● Factory Method Pattern giúp hạn chế sự phụ thuộc giữa creator và concrete
products.

● Factory Method Pattern giúp gom các đoạn code tạo ra product vào một nơi
trong chương trình, nhờ đó giúp dễ theo dõi và thao tác.
● Với Factory Method Pattern, chúng ta có thể thoải mái thêm nhiều loại
product mới vào chương trình mà không làm thay đổi các đoạn code nền
tảng đã có trước đó.

5. Viết đoạn code Client (hàm Main()) để khai thác (sử dụng mẫu)

public static void Main(String[] args)


{
Console.WriteLine("App: Launched with the ConcreteCreatorHonda.");
ClientCode(new ConcreteCreatorHonda());

Console.WriteLine("");

Console.WriteLine("App: Launched with the ConcreteCreatorLexus.");


ClientCode(new ConcreteCreatorLexus());
}

public void ClientCode(Creator creator)


{
// ...
Console.WriteLine("Client: I'm not aware of the creator's class," +
"but it still works.\n" + creator.SomeOperation());
// ...
}
6. Mô tả 01 ví dụ thực tế (càng gần gũi càng tốt) để minh họa cho mẫu.

Có 3 hãng Honda, Lexus và Toyota đều tính là “Car”. Cả 3 hãng này đều
mang thuộc tính của Car nên nó thừa hưởng tất cả các tính chất của Car và chỉ
khác mẫu xe(view) của Car. Tuy nó có chung phương thức nhưng chúng ta có thể
định nghĩa khác nhau cho nó. Hiểu đơn giản là bạn đến cửa hàng Honda để bạn
xem xe của hãng Honda chứ không phải xem của Nexus hay Toyota. Và 2 cửa
hàng kia cũng vậy. Cho nên Chúng ta phải viết nội dung của phương thức view()
khác nhau cho từng hãng xe(class con) bằng cách implement nó dựa trên Car.

Bạn muốn đi xem các hãng ô tô khác nhau mà không muốn đi tới từng cửa
hàng khác nhau. Vậy thì phải làm thế nào? Tạo một cửa hàng xe(CarFactory-
subclass). CarFactory đơn giản giống như là 1 cửa hàng có bán nhiều loại xe, bạn
chỉ việc tới đó và xem các loại ô tô khác nhau mà không cần phải đi lại nhiều.
Hoặc cách hiểu khác thì CarFactory giống như 1 thằng môi giới đi mồi chài bạn.
Nó có các kiến thức để tư vấn cho bạn về các loại xe mà bạn quan tâm.
Abstract Factory
1. Công dụng chính của mẫu

Cung cấp một Interface để dựng các method của các đối tượng liên quan
hoặc phụ thuộc mà không chỉ định các lớp cụ thể của chúng.

2. Các trường hợp nào có thể sử dụng mẫu

- Một phần mềm có lớp Abstract độc lập với cách các lớp con triển khai, lớp
Abstract chỉ thiết kế và đại diện cho cho nhóm con.
- Một phần mềm được cấu hình với nhiều lớp con khác nhau cùng thuộc một
lớp Abstract.
- Một nhóm lớp con cùng thuộc lớp Abstract được thiết kế để được sử dụng
cùng nhau và cần ràng buộc các lớp con lại với nhau.
- Cung cấp sẵn các hàm hoặc thuộc tính và chỉ muốn tiết lộ Interface chứ
không phải triển khai chi tiết.

3. Các thành phần (lớp) chính của mẫu.


Hình 2. Các thành phần của lớp Abstract Factory

● AbstractFactory: Khai báo giao diện cho các hoạt động tạo ra các Product
trừu tượng để các lớp con kế thừa triển khai.
● ConcreteFactory: Triển khai các hoạt động tạo ra các Product với từng lớp
con cụ thể cùng thuộc lớp AbstractFactory.
● AbstractProduct: Khai báo giao diện cho các hoạt động của lớp Product trừu
tượng.
● ConcreteProduct: Triển khai các hoạt động của lớp Product với từng lớp
con cụ thể tương ứng với các lớp con cụ thể thuộc lớp AbstractFactory.
● Client: Sử dụng các giao diện được khai báo ở lớp AbstractFatory và
AbstractProduct.
4. Những ưu điểm (điểm có lợi) khi sử dụng mẫu.

Ưu điểm:

● Chắc chắn rằng các lớp Factory cụ thể và lớp Product cụ thể tương
thích với nhau.

● Tránh việc kết nối chặt chẽ giữa Client và Product cụ thể.

● Single Responsibility Principle : Việc tách riêng code tạo sản phẩm qua
lớp Factory, làm việc xử lý dễ dàng hơn.

● Open/Closed Principle: Hỗ trợ cho việc tạo 1 Product mới dễ dàng


không ảnh hưởng đến code client đã tồn tại.

Nhược điểm:

+ Code có thể trở nên phức tạp hơn mức cần thiết vì rất nhiều Abstract
và lớp con thuộc lớp đó được tạo.
5. Viết đoạn code Client (hàm Main()) để khai thác (sử dụng mẫu).

class Client
{
public void Main()
{
Console.WriteLine("Client: Test với Factory 1: Window");
ClientMethod(new Window());
Console.WriteLine("--------------------------");

Console.WriteLine("Client: Test với Factory 2: Mac");


ClientMethod(new Mac());
}
public void ClientMethod(IAbstractFactory OS)
{
var Button = OS.CreateButton();
var Check = OS.CreateCheck();

Console.WriteLine(Button.StateButton());
Console.WriteLine(Check.StateCheck());
}
}

class Program
{
static void Main(string[] args)
{
new Client().Main();
}
}

6. Mô tả 01 ví dụ thực tế (càng gần gũi càng tốt) để minh họa cho mẫu.

Ví dụ: Hai hệ điều hành khác nhau (Window, Mac) ta sẽ có 2 sản phẩm tương ứng
khác nhau.

- Ta có lớp AbstractFactory là hệ điều hành (OS) khai báo hai hành động
CreateButton và CreateCheck.
- Lớp AbstractFactory có hai lớp con triển khai cụ thể là Window và Mac.
Triển khai chi tiết các hành động của lớp cha.

- Với lớp Window có hành động CreateButton liên kết với WinButton bên lớp
sản phẩm. Và hành động CreateCheck liên kết với WinCheck.

- Với lớp Mac có hành động CreateButton liên kết với MacButton bên lớp sản
phẩm. Và hành động CreateCheck liên kết với MacCheck.

- Ta tạo 2 lớp sản phẩm AbstractProduct là: Button và Check.

- Ta có lớp AbstractProduct: Button khai báo hành động StateButton. Có hai


lớp con triển khai là WinButton và MacButton.

- Ta triển khai cụ hành động StateButton cho hai lớp con cụ thể WinButton và
MacButton.

- Ta có lớp AbstractProduct: Check khai báo hành động StateCheck. Có hai


lớp con triển khai là WinCheck và MacCheck.

- Ta triển khai cụ hành động StateCheck cho hai lớp con cụ thể WinCheck và
MacCheck.

- Ta tạo 1 hàm để truyền tham số Factory vào. Ta tạo tham số Button bằng với
Button của Factory truyền vào và Check bằng với Check của Factory truyền
vào. Khi đó với mỗi tham số Factory truyền vào từ hàm chính ta sẽ có
StateButton và StateCheck tương ứng với Factory đó.
Builder
1. Công dụng chính của mẫu

Mẫu thiết kế này cho phép lập trình viên tạo ra những đối tượng phức tạp
nhưng chỉ cần thông qua các câu lệnh đơn giản để tác động nên các thuộc tính
của nó.

2. Các trường hợp nào có thể sử dụng mẫu

● Muốn thay đổi thiết kế cho việc lòng nhau của các hàm khởi tạo. Vấn đề này
phát sinh khi các lập trình viên làm việc với một lớp mà chứa rất nhiều thuộc
tính cần phải phải tạo ra nhiều hàm khởi tạo với số lượng các thuộc tính tăng
dần.

● Cần tạo ra một đối tượng phức tạp, một đối tượng mà thuật toán để tạo lập
các thuộc tính độc lập với các thuộc tính khác.

● Muốn kiểm soát quá trình xây dựng.

● Khi người dùng (client) mong đợi nhiều cách khác nhau cho đối tượng được
xây dựng.
3. Các thành phần (lớp) chính của mẫu

Hình 3. Các thành phần chính của mẫu Builder.

● Builder: là thành phần định nghĩa một lớp trừu tượng (abstract class) để tạo
ra một hoặc nhiều phần của đối tượng product.
● ConcreateBuilder: là thành phần triển khai, cụ thể hóa các lớp trừu tượng
để tạo ra các thành phần và tập hợp các thành phần đó với nhau. Thành
phần này sẽ xác định và nắm giữ các thể hiện mà nó tạo ra và nó cũng cung
cấp các phương thức để trả các thể hiện mà nó đã tạo ra trước đó.
● Product : thành phần này trong bài viết sẽ đại diện cho đối tượng phức tạp
phải tạo ra.
● Director: thành phần này sẽ khởi tạo đối tượng Builder.
4. Những ưu điểm (điểm có lợi) khi sử dụng mẫu.

● Hỗ trợ, loại bớt việc phải viết nhiều constructor.


● Code dễ đọc, dễ bảo trì hơn khi số lượng thuộc tính bắt buộc để tạo một
object từ 4 hoặc 5 properly.
● Có thể tạo đối tượng immutable.
● Đối tượng được xây dựng an toàn hơn: bởi vì nó đã được tạo hoàn chỉnh
trước khi sử dụng.

5. Viết đoạn code Client (hàm Main()) để khai thác (sử dụng mẫu)

public static void Main(String[] args)


{
var director = new Director();
var builder = new ConcreteBuilder();
director.Builder = builder;

Console.WriteLine("Standard basic product:");


director.buildMinimalViableProduct();
Console.WriteLine(builder.GetProduct().ListParts());

Console.WriteLine("Standard full featured product:");


director.buildFullFeaturedProduct();
Console.WriteLine(builder.GetProduct().ListParts());

Console.WriteLine("Custom product:");
builder.BuildPartA();
builder.BuildPartC();
Console.Write(builder.GetProduct().ListParts());
}
6. Mô tả 01 ví dụ thực tế (càng gần gũi càng tốt) để minh họa cho mẫu.

● Ô tô và hướng dẫn sử dụng ô tô. 1 chiếc xe ô tô là một đối tượng phức tạo có
thể được xây dựng theo nhiều cách khác nhau. Thay vì thiết kế 1 chiếc xe
cần một bản kiến trúc khổng lồ thì ở đây chúng ta chia nhỏ chiếc xe thành
các bộ phận linh kiện(builder class). Những bộ phận này có những phương
thức(methods) để cấu tạo nên các bộ phận của chiếc xe.

● Khi khách hàng cần lắp ráp một ô tô, cần tinh chỉnh một chiếc xe hơi thì có
thể làm việc trực tiếp với người xây dựng. Mặt khác có thể ủy thác lắp ráp
cho lớp director. Mỗi chiếc xe đều cần một hướng dẫn. Hướng dẫn mô tả
mọi tính năng của xe vì vậy các chi tiết trong hướng dẫn sử dụng khác nhau
giữa các mô hình khác nhau.Đó là lý do tại sao nên sử dụng lại một quy trình
xây dựng hiện có cho cả xe thật và hướng dẫn sử dụng tương ứng. Xây dựng
1 hướng dẫn không giống như xây dựng 1 chiếc xe do đó cần phải cung cấp
một lớp xây dựng khác chuyên soạn thảo hướng dẫn sử dụng. Lớp này thực
hiện các phương pháp xây dựng tương tự như anh chị em chế tạo xe hơi của
nó, nhưng thay vì chế tạo các bộ phận xe hơi, nó mô tả chúng. Bằng cách
chuyển những người xây dựng này đến cùng một đối tượng director để có
thể xây dựng một chiếc xe hơi hoặc một hướng dẫn.
Prototype
1. Công dụng chính của mẫu

Prototype Pattern là một pattern thuộc nhóm Creational Patterns. Về bản


chất, loại design pattern này cung cấp cơ chế cho phép khởi tạo một đối tượng
bằng cách sao chép từ một đối tượng khác đã tồn tại thay vì sử dụng toán tử new.
Đối tượng mới là một bản sao có thể giống hoàn toàn hoặc đã được thay đổi một số
thuộc tính so với đối tượng gốc, chúng ta có thể thoải mái thay đổi dữ liệu của đối
tượng bản sao này mà không làm ảnh hưởng đến đối tượng gốc kia.

2. Các trường hợp nào có thể sử dụng mẫu

● Chúng ta muốn hạn chế phân lớp và giảm số lượng các lớp con cho việc
khởi tạo đối tượng.

● Chúng ta muốn truyền một đối tượng nào đó vào một hàm để xử lý, thay vì
truyền thẳng đối tượng gốc (có thể ảnh hưởng dữ liệu) thì chúng ta có thể
truyền vào đối tượng sao chép của nó.

● Chi phí của việc tạo ra đối tượng mới bằng cách sử dụng toán tử new là khá
lớn.
3. Các thành phần (lớp) chính của mẫu

Prototype Pattern bao gồm ba thành phần cơ bản là: Prototype, Concrete Prototype
và Client.

Hình 4 : Cấu trúc của một Prototype pattern

● Prototype: Là một class, interface hoặc abstract class trong đó có chứa


phương thức clone().

● Concrete Prototype: Các lớp này có nhiệm vụ thực thi interface (hoặc kế
thừa từ class) Prototype để định nghĩa phương thức copy của chính bản thân
nó. Chúng ta hoàn toàn có thể bỏ qua lớp này nếu Prototype là một class và
đã định nghĩa phương thức clone() của chính nó.

● Client: Là nơi khởi tạo đối tượng bằng cách gọi tới Concrete Prototype
tương ứng để thực hiện việc clone chính nó.
4. Những ưu điểm (điểm có lợi) khi sử dụng mẫu.

● Prototype Pattern giúp giảm chi phí, thời gian và góp phần làm tăng hiệu
suất của chương trình do không sử dụng toán tử new để tạo ra đối tượng
mới.

● Prototype Pattern giúp giảm độ phức tạp cho việc khởi tạo đối tượng: do mỗi
lớp chỉ implement cách clone của chính nó.

● Với Prototype Pattern, chúng ta có thể hạn chế việc phân lớp và tạo ra nhiều
lớp con cho việc khởi tạo đối tượng như của Abstract Factory Pattern.

● Prototype Pattern giúp tăng tính linh động của hệ thống vì nó cho phép khởi
tạo đối tượng mới bằng cách thay đổi một vài thuộc tính của đối tượng gốc
được nó sao chép.
5. Viết đoạn code Client (hàm Main()) để khai thác (sử dụng mẫu)

class Program
{
static void Main(string[] args)
{
Console.WriteLine("***Prototype Pattern Demo***\n");
//Base or Original Copy
BasicCar nano_base = new Nano("Green Nano") { Price = 100000 };
BasicCar ford_base = new Ford("Ford Yellow") { Price = 500000 };
BasicCar bc1;

//Nano
bc1 = nano_base.Clone();
bc1.Price = nano_base.Price + BasicCar.SetPrice();
Console.WriteLine("Car is: {0}, and it's price is Rs. {1}",
bc1.ModelName,
bc1.Price);

//Ford
bc1 = ford_base.Clone();
bc1.Price = ford_base.Price + BasicCar.SetPrice();
Console.WriteLine("Car is: {0}, and it's price is Rs. {1}",
bc1.ModelName,
bc1.Price);
Console.ReadLine();
}
}

6. Mô tả 01 ví dụ thực tế (càng gần gũi càng tốt) để minh họa cho mẫu.

Một nhân viên bán hàng của cửa hàng xe khi nhận được công việc viết thông
tin của các loại xe, nhân viên này soạn ra một file liệt kê những nội dung chung
liên quan đến mô tả xe như: tên xe, màu sắc, giá tiền, kic, xuất xứ,... Sau đó, photo
ra nhiều bản rồi điền thông tin chi tiết cho từng loại xe khác nhau.

Ví dụ:
Xe Ford Xe Mercedes-Benz

Tên xe: Ford Ranger XLS 4x2 AT Tên xe: Mercedes-Benz GLS580 4Matic

Màu sắc: Trắng Màu sắc: Đỏ

Giá tiền: 700,000,000 VND Giá tiền: 2,500,000,000 VND

Kích thước: 5362 x 1860 x 1830 Kích thước: 5212 x 2156 x 1824

Xuất xứ: Mỹ Xuất xứ: Đức


Singleton
1. Công dụng chính của mẫu

Một mẫu thuộc nhóm Creational Design Pattern. Single Pattern là một
design pattern mà:

● Đảm bảo rằng một class chỉ có duy nhất một instance.
● Và cung cấp một cách toàn cầu (global) để truy cấp tới instance đó.

2. Các trường hợp nào có thể sử dụng mẫu

● Bạn gặp một sự cố về hiệu năng hệ thống. Cùng một thời điểm, các bạn đang
sử dụng một lúc nhiều đối tượng và chúng làm tiêu tốn quá nhiều tài nguyên
của hệ thống. Đây là vấn đề mà bạn cần phải khắc phục, và Singleton pattern
có thể giúp bạn thực hiện được điều đó.

● Khi bạn phải xử lý 1 đối tượng nhạy cảm mà dữ liệu của nó không thể chia
sẻ cho mọi thể hiện.
3. Các thành phần (lớp) chính của mẫu

Hình 5. Thành phần (lớp) chính của mẫu Singleton

- Tạo một lớp controller(Singleton) quản lý và lưu trữ đảm bảo tính duy nhất.
(hoặc tạo một lớp để cache object).

+ Lớp Singleton này khai báo phương thức tĩnh getInstance trả về cùng
thể hiện của lớp của chính nó.

+ Hàm tạo của Singleton nên được ẩn khỏi mã máy khách. Gọi
getInstance phương thức nên là cách duy nhất để có được đối tượng
Singleton.
4. Những ưu điểm (điểm có lợi) khi sử dụng mẫu.

● Quản lý việc truy cập tốt hơn vì chỉ có một thể hiện đơn nhất.
● Cho phép cải tiến lại các tác vụ (operations) và các thể hiện (representation)
do pattern có thể được kế thừa và tùy biến lại thông qua một thể hiện của lớp
con
● Quản lý số lượng thể hiện của một lớp, không nhất thiết chỉ có một thể hiện
mà có số thể hiện xác định.
● Khả chuyển hơn so với việc dùng một lớp có thuộc tính là static, vì việc
dùng lớp static chỉ có thể sử dụng một thể hiện duy nhất, còn Singleton
Pattern cho phép quản lý các thể hiện tốt hơn và tùy biến theo điều kiện cụ
thể.
5. Viết đoạn code Client (hàm Main()) để khai thác (sử dụng mẫu)

static void Main(string[] args)


{
// The client code.
Singleton turn = Singleton.GetInstance();
Singleton off = Singleton.GetInstance();

if (turn == off)
{
Console.WriteLine("Singleton works, both variables contain the
same instance.");
}
else
{
Console.WriteLine("Singleton failed, variables contain different
instances.");
}
}

6. Mô tả 01 ví dụ thực tế (càng gần gũi càng tốt) để minh họa cho mẫu.

Giả sử trong ứng dụng có chức năng bật tắt nhạc nền chẳng hạn, khi người
dùng mở app thì ứng dụng sẽ tự động mở nhạc nền và nếu người dùng muốn tắt thì
phải vào setting trong app để tắt nó, trong setting của app cho phép người dùng
quản lý việc mở hay tắt nhạc, và trong trường hợp này bạn sẽ cần sử dụng
singleton để quản lý việc này. Chắc chắn bạn phải cần duy nhất 1 instance để có
thể ra lệnh bật hay tắt, tại sao ? vì đơn giản bạn không thể tạo 1 instance để mở
nhạc rồi sau đó lại tạo 1 instance khác để tắt nhạc, lúc này sẽ có 2 instance được
tạo ra, 2 instance này không liên quan đến nhau nên không thể thực hiện thực hiện
việc cho nhau được, bạn phải hiểu rằng instance nào bật thì chỉ có instance đó mới
được phép tắt nên dẫn đến phải cần 1 instance.

You might also like