Design Pattern: Method Factory (phần 2)

Design Pattern: Method Factory (phần 2)

Trong bài viết trước, tôi có giới thiệu về Abstract factory, trong bài viết này tôi sẽ trình bày một design pattern khác là Method factory. Method factory định nghĩa một interface cho phép tạo ra đối tượng nhưng nó để cho lớp con quyết định khởi tạo thể hiện của lớp nào. Mức độ sử dụng của method factory cũng tương đối thường gặp giống nhu abstract factory.

UML

Method factory được mô hình hóa bởi UML như sau:

Các thành phần tham gia

  • Product: định nghĩa interface của đối tượng mà phương thức factory sẽ sinh ra
  • ConcreteProduct: Cài đặt các thuộc tính và phương thức virtual quy định trong Product
  • Creator: Khai báo phương thức factory (trả về đôi tượng kiểu Product), Creator cũng có thể định nghĩa phần cài đặt cho phương thức factory mặc định trả về ConcreteProduct mặc định
  • ConcreteCreator: override phương thức factory của Creator và trả về ConcreteProduct tương ứng

Cài đặt Method factory trong C#

Để đơn giản, các ConcreteProduct không cài đặt gì, code mẫu chỉ khởi tạo các đối tượng và hiển thị tên các đối tượng được khởi tạo:

class MainApp
{
	static void Main()
	{
		// Mảng các Creator
		Creator[] creators = new Creator[2];
 
		creators[0] = new ConcreteCreatorA();
		creators[1] = new ConcreteCreatorB();
 
		// Duyệt các Creator và tạo Product
		foreach (Creator creator in creators)
		{
			Product product = creator.FactoryMethod();
			Console.WriteLine("Created {0}", product.GetType().Name);
		}
 
		Console.ReadKey();
	}
}
 
/// <summary>
/// The 'Product' abstract class
/// </summary>
abstract class Product
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class ConcreteProductA : Product
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class ConcreteProductB : Product
{
}
 
/// <summary>
/// The 'Creator' abstract class
/// </summary>
abstract class Creator
{
	public abstract Product FactoryMethod();
}
 
/// <summary>
/// A 'ConcreteCreator' class
/// </summary>
class ConcreteCreatorA : Creator
{
	public override Product FactoryMethod()
	{
		return new ConcreteProductA();
	}
}
 
/// <summary>
/// A 'ConcreteCreator' class
/// </summary>
class ConcreteCreatorB : Creator
{
	public override Product FactoryMethod()
	{
		return new ConcreteProductB();
	}
}

Kết quả:

Created ConcreteProductA
Created ConcreteProductB

Một ví dụ trong thực tế

Trong thế giới thực, Method factory rất linh hoạt trong việc tạo ra các văn bản khác nhau (Document). Văn bản được chia thành 2 loại là Báo cáo (Report) và Sơ yếu lí lịch (Resume). Trong đó báo cáo bao gồm các phần: trang giới thiệu (IntroductionPage), các kết quả (ResultsPage), kết luận (ConclusionPage), tổng hợp (SummaryPage) và phần mục lục tham khảo (BibliographyPage). Trong khi sơ yếu lí lịch lại có các phần: kỹ năng (SkillsPage), quá trình học tập (EducationPage) và kinh nghiệm làm việc (ExperiencePage). Khi đó factory method sẽ giúp ta cài đặt như sau:

class MainApp
{
	static void Main()
	{
		// Khi new object mới gọi phương thức factory
		Document[] documents = new Document[2];
 
		documents[0] = new Resume();
		documents[1] = new Report();
 
		// Hiển thị danh sách tên các mục
		foreach (Document document in documents)
		{
			Console.WriteLine("\n" + document.GetType().Name + "-------");
			foreach (Page page in document.Pages)
			{
				Console.WriteLine(" " + page.GetType().Name);
			}
		}
 
		Console.ReadKey();
	}
}
 
/// <summary>
/// The 'Product' abstract class
/// </summary>
abstract class Page
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class SkillsPage : Page
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class EducationPage : Page
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class ExperiencePage : Page
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class IntroductionPage : Page
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class ResultsPage : Page
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class ConclusionPage : Page
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class SummaryPage : Page
{
}
 
/// <summary>
/// A 'ConcreteProduct' class
/// </summary>
class BibliographyPage : Page
{
}
 
/// <summary>
/// The 'Creator' abstract class
/// </summary>
abstract class Document
{
	private List<Page> _pages = new List<Page>();
 
	// Trong hàm khởi tạo gọi đến phương thức factory
	public Document()
	{
		this.CreatePages();
	}
 
	public List<Page> Pages
	{
		get { return _pages; }
	}
 
	// Factory Method
	public abstract void CreatePages();
}
 
/// <summary>
/// A 'ConcreteCreator' class
/// </summary>
class Resume : Document
{
	// Cài đặt Factory Method
	public override void CreatePages()
	{
		Pages.Add(new SkillsPage());
		Pages.Add(new EducationPage());
		Pages.Add(new ExperiencePage());
	}
}
 
/// <summary>
/// A 'ConcreteCreator' class
/// </summary>
class Report : Document
{
	// Cài đặt Factory Method
	public override void CreatePages()
	{
		Pages.Add(new IntroductionPage());
		Pages.Add(new ResultsPage());
		Pages.Add(new ConclusionPage());
		Pages.Add(new SummaryPage());
		Pages.Add(new BibliographyPage());
	}
}

Kết quả:

Resume -------
SkillsPage
EducationPage
ExperiencePage

Report -------
IntroductionPage
ResultsPage
ConclusionPage
SummaryPage
BibliographyPage

Khi trích dẫn bài viết từ tek.eten.vn, xin vui lòng ghi rõ nguồn. Chúng tôi sẽ rất cảm ơn bạn!