Tìm hiểu Factory Design Pattern với ví dụ sử dụng ngôn ngữ C#
Đăng lúc: 01:47 PM - 04/11/2022 bởi Charles Chung - 1085Factory Design Pattern là một mẫu thiết kế thuộc nhóm Creational, nó giải quyết vấn đề khởi tạo một đối tượng mới mà không cần thiết phải chỉ ra một cách chính xác class nào sẽ được khởi tạo.
1. Factory Design Pattern trong C# là gì?
Về mặt kỹ thuật, chúng ta có thể nói rằng Factory là một lớp có một phương thức. Phương thức đó sẽ tạo và trả về các loại đối tượng khác nhau dựa trên tham số đầu vào mà nó nhận được. Nói một cách đơn giản, nếu chúng ta có một lớp cha và n số lớp con, và dựa trên dữ liệu được cung cấp, nếu chúng ta phải tạo và trả về đối tượng của một trong các lớp con, thì chúng ta cần sử dụng Factory Design Pattern trong C #.
Trong mẫu Factory Design, tôi tạo một đối tượng mà không để lộ logic tạo đối tượng cho client và client sẽ tham chiếu đến đối tượng mới được tạo bằng interface chung. Nguyên tắc cơ bản đằng sau mô hình thiết kế factory là tại thời điểm chạy chúng ta nhận được một đối tượng có kiểu tương tự dựa trên tham số mà chúng ta truyền vào.
Để hiểu rõ hơn Mô hình thiết kế Factory trong C # chúng ta hãy xem một ví dụ thực tế như sau:
Ở đây, tôi có ba lớp thẻ tín dụng là MoneyBack, Titanium và Platinum và ba lớp này là các lớp con thực thi từ một giao diện ICreditCard. Giao diện ICreditCard có ba phương thức là GetCardType, GetCreditLimit và GetAnnualCharge. Các lớp con MoneyBack, Titanium và Platinum sẽ thực thi các phương thức trên.
Yêu cầu của tôi là khi người dùng chọn thẻ tín dụng thì chương trình cần hiển thị thông tin bắt buộc của thẻ đã chọn đó. Đầu tiên chúng ta hãy thảo luận về cách đạt được điều này mà không cần sử dụng Factory Design Pattern trong C #. Sau đó, chúng ta sẽ thảo luận về các vấn đề và cuối cùng, chúng ta sẽ tạo ứng dụng tương tự bằng cách sử dụng Factory Design Pattern trong C #.
Phương pháp không sử dụng Factory Design Pattern
namespace WithoutUsingFactoryDesignPattern
{
interface ICreditCard
{
//phương thức trả về tên loại thẻ
string GetCardType();
//phương thức trả về giới hạn số tiền trong thẻ
int GetCreditLimit();
//phương thức trả về phí thường niên
int GetAnnualCharge();
}
/// <summary>
/// Lớp MoneyBack thực thi từ Interface ICreditCard
/// </summary>
class MoneyBack : ICreditCard
{
public int GetAnnualCharge()
{
return 200;
}
public string GetCardType()
{
return "MoneyBack";
}
public int GetCreditLimit()
{
return 20000;
}
}
/// <summary>
/// Lớp Platinum thực thi từ Interface ICreditCard
/// </summary>
class Platinum : ICreditCard
{
public int GetAnnualCharge()
{
return 1000;
}
public string GetCardType()
{
return "Platium Plus";
}
public int GetCreditLimit()
{
return 50000;
}
}
/// <summary>
/// Lớp Titanium thực thi từ Interface ICreditCard
/// </summary>
class Titanium :ICreditCard
{
public int GetAnnualCharge()
{
return 500;
}
public string GetCardType()
{
return "Titanium Edge";
}
public int GetCreditLimit()
{
return 30000;
}
}
}
//Chương trình chính
namespace WithoutUsingFactoryDesignPattern
{
class Program
{
static void Main(string[] args)
{
string cardType = null;
ICreditCard credit = null;
Console.Write("Enter type of card:");
cardType = Console.ReadLine();
if(cardType =="MoneyBack")
{
credit = new MoneyBack();
}else if(cardType=="Titanium")
{
credit = new Titanium();
}else if(cardType=="Platinum")
{
credit = new Platinum();
}
if(credit!=null)
{
Console.WriteLine("Type of card:"+ credit.GetCardType());
Console.WriteLine("Credit Limit:$ "+ credit.GetCreditLimit().ToString("#,###"));
Console.WriteLine("Annual Charge:$ "+credit.GetAnnualCharge().ToString("#,###"));
}
else
{
Console.WriteLine("Invalid Card Type");
}
}
}
}
Vấn đề gặp phải là
- Client (Program Main) liên kết chặt chẽ với các sản phẩm Credit Card.
- Nếu tôi thêm một Credit Card mới, thì tôi cũng cần sửa đổi phương thức Main bằng cách thêm một điều kiện bổ sung if-else không chỉ chi phí phát triển mà còn trong quá trình thử nghiệm.
Để khắc phục vấn đề trên chúng ta hãy xem xét Phương pháp sử dụng Factory Design Pattern sau đây
Chúng ta vẫn giữ nguyên code của giao diện ICreditCar và 3 lớp MoneyBack, Titanium, Platinum. Tuy nhiên, chúng ta sẽ bổ sung thêm 1 lớp CreditCardFactory với một phương thức tĩnh GetCreditCard nhận tham số đầu vào là cardType, phương thức này có nhiệm vụ tạo và trả về đối tượng thẻ cần tạo tùy thuộc vào tham số đầu vào là cardType.
/// <summary>
/// Lớp CreditCardFactory cung cấp 1 phương thức
/// có nhiệm vụ tạo và trả về đối tượng Credit Card
/// theo tham số truyền vào là cardType
/// </summary>
class CreditCardFactory
{
public static ICreditCard GetCreditCart(string cardType)
{
if (cardType == "MoneyBack")
{
return new MoneyBack();
}
else if (cardType == "Titanium")
{
return new Titanium();
}
else if (cardType == "Platinum")
{
return new Platinum();
}
return null;
}
}
//Chương trình chính
class Program
{
static void Main(string[] args)
{
Console.Write("Enter type of card:");
var cardType = Console.ReadLine();
ICreditCard credit = CreditCardFactory.GetCreditCart(cardType);
if (credit != null)
{
Console.WriteLine("Type of card:" + credit.GetCardType());
Console.WriteLine("Credit Limit:$ " + credit.GetCreditLimit().ToString("#,###"));
Console.WriteLine("Annual Charge:$ " + credit.GetAnnualCharge().ToString("#,###"));
}
else
{
Console.WriteLine("Invalid Card Type");
}
}
}
Như vậy chúng ta đã giải quyết được 2 vấn đề trên. Mọi giải đáp thắc mắc, mời các bạn comment bên dưới bài viết.
Link tải ví dụ trong bài viết (Google Drive)
thay lời cảm ơn!
Các bài cũ hơn
- Giới thiệu các phiên bản Visual Studio Community 2017-2019-2022 (03:24 PM - 03/11/2022)
- Làm thế nào để Tìm kiếm-Lọc-Phân trang dữ liệu trong ASP.NET Core (09:48 AM - 03/11/2022)
- Làm thế nào để tạo Area và Layout trong ASP.NET Core (09:28 AM - 31/10/2022)
- Tìm hiểu Singleton Design Pattern với ví dụ sử dụng ngôn ngữ C# (09:41 AM - 27/10/2022)
- Truy xuất dữ liệu trong ASP.NET Core 2.1 sử dụng Entity Framework Core(Database First) (09:45 AM - 25/10/2022)