[Tutorial] Design Pattern – Factory Pattern

0
46

 “Creates an instance of several families of classes”

The purpose of the Abstract Factory is to provide an interface for creating families of related objects, without specifying concrete classes. This pattern is found in the sheet metal stamping equipment used in the manufacture of Japanese automobiles. The stamping equipment is an Abstract Factory which creates auto body parts. The same machinery is used to stamp right hand doors, left hand doors, right front fenders, left front fenders, hoods, etc. for different models of cars.

Rules of thumb

  • Abstract Factory classes are often implemented with Factory Methods, but they can be implemented using Prototype.
  • Factory Methods are usually called within Template Methods.
  • Factory Method: creation through inheritance. Prototype: creation through delegation.
  • Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward AbstractFactory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.
  • Prototype doesn’t require subclassing, but it does require an Initialize operation. Factory Method requires subclassing, but doesn’t require Initialize.
  • The advantage of a Factory Method is that it can return the same instance multiple times, or can return a subclass rather than an object of that exact type.
  • Some Factory Method advocates recommend that as a matter of language design (or failing that, as a matter of style) absolutely all constructors should be private or protected. It’s no one else’s business whether a class manufactures a new object or recycles an old one.
  • The new operator considered harmful. There is a difference between requesting an object and creating one. The newoperator always creates an object, and fails to encapsulate object creation. A Factory Method enforces that encapsulation, and allows an object to be requested without inextricable coupling to the act of creation.

Design Pattern - Factory Pattern

Download full source code here

Tại đây, công ty MegaGigaCo, bạn được trả lương cao cho kỹ năng thiết kế mẫu chuyên nghiệp của mình, bạn đang tạo một đối tượng kết nối cơ sở dữ liệu mới

cConnection conn = new cOracleConnection();
“Không tồi,” bạn nghĩ, sau khi hoàn thành đoạn mã việc lớp OracleConnection. Bây giờ bạn đã có thể kết nối với cơ sở dữ liệu Oracle.
“Nhưng,” Giám đốc điều hành la lên ,”làm thế nào để kết với máy chủ cơ sở dữ liệu Microsof SQL Server?”
“Được”, bạn nói “Bình tĩnh, để tôi suy nghĩ một lát”. Bạn ra khỏi phòng để ăn trưa và sau đó quay lại tìm giám đốc và ban quản trị. Mọi người nóng lòng chờ đợi và hỏi “Mọi việc đã xong chưa?”
Bạn trở lại làm việc và tạo ra một lớp mới dùng để kết nối cơ sở dữ liệu, lớp SQLServerConnection.

cConnection conn = new cSqlServerConnecton();

“Tốt lắm” Vị giám đốc nói. “Umh, vậy làm sao để kết nối với MySQL? Chúng ta muốn nó là kết nối mặc định”. “Woa”, bạn hơi bối rối. Tuy nhiên bạn vẫn làm thêm một kết nối với MySQL như sau:

cConnection conn = new cMySqlServerConnecton();

Hiện tại bạn đã có ba loại kết nối cơ sở dữ liệu như sau: Oracle, SQL Server và MySQL. Vì vậy bạn chỉnh sửa mã nguồn cho phù hợp với các biến như “Oracle”, “SQL Server” hay bất cứ biến nào khác như sau:

if (type.equals("Oracle"))
    conn = new cOracleConnection();
   

else if (type.equals("SQL Server"))
    conn = new cSqlServeverConnection();   

else
    conn = new cMySqlServerConnection();

Tuyệt, bạn nghĩ. Không có gì khó khăn ở đây. 
“Tin xấu” Vị giám đốc nói lớn trong khi chạy ào vào phòng làm việc của bạn. “Chúng ta cần phải chỉnh sửa lại mã nguồn để xử lý các kết nối an toàn cho tất cả máy chủ cơ sở dữ liệu. Hội đồng quản trị của khu vực Western yêu cầu như vậy” 
Bạn đưa vị giám đốc ra khỏi phòng và ngồi suy nghĩ. Tất cả mã nguồn chắc phải chỉnh sửa lại. Phương thức mới createConnection, phần chính của mã nguồn, sẽ phải chỉnh sửa lại.
Có lẽ đây là lúc nghĩ về việc tách rời phần mã nguồn dễ thay đổi ra khỏi chương trình chính, phần tạo kết nối cơ sở dữ liệu connection, và đóng gói nó vào một đối tượng. Và đối tượng đó chính là mẫu nhà máy Factory. Đối tượng là một nhà máy, được viết trong mã nguồn, nhằm tạo ra các đối tượng kết nối connection. 
Vì sao bạn nghĩ tới mẫu thiết kế nhà máy Factory. Đây là những gợi ý: 
– Bạn sử dụng toán tử new để tạo đối tượng OracleConnection 
– Sau đó lại sử dụng tiếp toán tử new để tạo đối tượng SQLServerConnection, và sau đó là MySQLConnection. Nói cách khác, bạn đã sử dụng toán tử new để tạo nhiều đối tượng thuộc các lớp khác nhau, điều này làm mã nguồn của bạn trở nên lớn hơn và bạn buộc phải lặp lại điều này nhiều lần trong toàn bộ mã nguồn. 
– Sau đó bạn đưa đoạn mã đó vào trong một phương thức 
– Bởi vì yêu cầu vẫn còn có thể thay đổi nhanh chóng, nên cách tốt nhất là đóng gói chúng vào một đối tượng nhà máy factory. Theo cách làm này, bạn đã tách phần mã dễ thay đổi riêng biệt ra và giúp phần mã nguồn còn lại giữ vững nguyên tắc “đóng cho việc sửa đổi” 
Chúng ta có thể nói rằng, toán tử new vẫn tốt trong mọi trường hợp, nhưng khi mã tạo dựng đối tượng bị liên tục thay đổi, ta nên nghĩ đến việc đóng gói chúng bằng mẫu thiết kế nhà máy factory.
Ghi nhớ: Theo sách GoF, mẫu thiết kế phương thức nhà máy Factory Method được định nghĩa “Định nghĩa một giao diện để tạo một đối tượng, nhưng cho phép các lớp con quyết định cách thức thể hiện nó. Phương thức nhà máy Factory cho phép một lớp trì hoãn việc hiện thực của nó qua các lớp con”

1st Exam:

abstract class Address
{
public abstract void Show();
}

abstract class Phone
{
public abstract void Show();
}

abstract class Factory
{
virtual public Address createAddress()
{
return null;
}
virtual public Phone createPhone()
{
return null;
}
}

class USAddress: Address
{
public override void Show()
{
Console.WriteLine("USA Address");
}
}

class USPhone: Phone
{
public override void Show()
{
Console.WriteLine("USA Phone");
}
}

class VNAddress: Address
{
public override void Show()
{
Console.WriteLine("Viet Nam address");
}
}

class VNPhone:Phone
{
public override void Show()
{
Console.WriteLine("Viet Nam phone");
}
}

class USFactory: Factory
{
public override Address createAddress()
{
return new USAddress();
}
public override Phone createPhone()
{
return new USPhone();
}
}

class VNFactory:Factory
{
public override Address createAddress()
{
return new VNAddress();
}
public override Phone createPhone()
{
return new VNPhone();
}
}

class Program
{
static void Main(string[] args)
{
Factory factory = new VNFactory();
Address address = factory.createAddress();
Phone phone = factory.createPhone();

Console.WriteLine("Create Object by VNFactory");
address.Show();
phone.Show();

factory = new USFactory();
address = factory.createAddress();
phone = factory.createPhone();

Console.WriteLine("Create Object by USFactory");
address.Show();
phone.Show();

Console.ReadKey();
}
}

2nd Exam:


Ref:
https://sourcemaking.com/design_patterns/factory_method
https://haihth.wordpress.com/2013/02/21/dp-chapter3/