Showing posts with label Factory Method. Show all posts
Showing posts with label Factory Method. Show all posts

Phỏng vấn 2 mẫu thiết kế Abstract Factory và Factory Pattern

Interview Abstract Factory and Factory Method (Design Patterns)



Nguyễn Thoại
: Chà chà, chào hai anh, đây là lần đầu tiên blog của iem phỏng vấn hai anh, hai anh cảm thấy thế nào.

Factory Method: Tôi ko biết sao hay bị gộp chúng với cha Abstract Factory. Đều là factory pattern không có nghĩa chúng tôi không được có những buổi phỏng vấn riêng.:bbpcaycu:

Nguyễn Thoại: Ấy ấy, đừng tự ái, em muốn phỏng vấn cả hai anh cùng nhau để giúp đọc giả phân biệt được ai là ai. Hai anh có nhiều điểm giống nhau, và em có nghe vài phàn nàn rằng người ta thỉnh thoảng bị rối và không thể phân biệt được 2 người.

Abstract Factory: Ừ đúng đấy, đã có lúc tôi bị nhầm lẫn là cha Factory Method, và tôi biết ổng cũng bị giống như tôi. Hai tụi tôi đều giỏi trong việc giảm sự phụ thuộc giữa chương trình với những cài đặt cụ thể; nhưng mỗi người chúng tôi lại có những cách làm riêng nên thỉnh thoảng dân lập trình lại cảm thấy rối và không thể xác định được phải dùng cách nào.:bbpcuoi3:

Factory Method: Ấy, người ta vẫn phân biệt được tôi mà. Nói chung, tôi dùng các lớp để tạo ra products, còn cha dùng những đối tượng; hai cách đó hoàn toàn khác nhau nhé.

Nguyễn Thoại: Ừ em có tìm hiểu về hai anh rồi mà vẫn còn rối đây này, anh có thể nói thêm về khoản này không, anh Factory Method?:big_smile:

Factory Method: Ok, Cả cha Abstract Factory và tôi đều tạo ra các products, các objects, đó là việc chúng tôi phải làm. Nhưng tôi làm nhờ vào sự kế thừa (inheritance) …

Abstract Factory: … còn tôi làm nhờ vào sự kết hợp các đối tượng.

Factory Method: Đúng thía, nghĩa là nếu muốn tạo ra các đối tượng bằng cách Factory Method, người ta cần phải extend một lớp và override lại hàm tạo “factory method”.

Nguyễn Thoại: …rồi factory method sẽ làm cái gì?

Factory Method: Tất nhiên là tạo ra 1 object roài, anh đã từng viết bài về tôi mà giờ còn hỏi hả. Ý tưởng của tôi, Factory Method Pattern, là sẽ sử dụng các lớp con để sinh ra 1 đối tượng mong muốn. Bằng cách đó, người dùng sẽ chỉ cần biết đến lớp trừu tượng như gia cầm, và các lớp con cụ thể sẽ lo về các kiểu gà, kiểu vịt, kiểu ngan. Vì vậy, nói theo cách khác, tôi giúp chương trình độc lập với các kiểu (type) cụ thể đó.:bbpskien:

Abstract Factory: Ý tưởng của tôi cũng giống giống vậy đó, nhưng chỉ là làm theo một cách khác…

Nguyễn Thoại: Tiếp đi anh Abstract Factory … vừa rồi anh có đề cập đến cách kết hợp các đối tượng?

Abstract Factory: Ờ,cách của tôi thế này: Tôi tạo ra một kiểu trừu tượng (abstract type) để dùng vào việc tạo ra một nhóm những products khác. Khi đó, những lớp con của kiểu trừu tượng sẽ xác định cách tạo ra các products này. Để áp dụng được ý tưởng của tôi, bạn phải tạo ra một instance của một trong các lớp con trên (instance này là 1 factory) và đưa nó vào chỗ cần thiết trong code. Vì thế, giống như Factory Method, những nơi sử dụng factory của tôi sẽ hoàn toàn độc lập với những produtcts cụ thể.

Nguyễn Thoại: Oh yè, tôi biết rồi, một lợi ích nữa của cách này là anh đã nhóm các products tương tự nhau lại, có đúng không?

Abstract Factory: Đúng roài cưng à.:bbpchao:

Nguyễn Thoại: Bây giờ người ta cần bổ sung thêm một product nữa vô nhóm các products mà anh có thể tạo ra. Vậy không cần phải thay đổi gì hết huh?

Abstract Factory: Hèm, trường hợp này thì tôi phải thay đổi chút ít, nhiều người không thích lắm ở điểm này.

Factory Method: hĩ hĩ:bbpcuoi3:

Abstract Factory: Cười gì cha nội?:bbpbuon:

Factory Method: Cười chứ sao ko cười, làm vậy quá mất công chứ gì nữa. Cha thay đổi có nghĩa là người dùng phải đi mà đổi tất cả các lớp con roài? (các lớp con ở đây là các factories)

Abstract Factory: Đúng, nhưng cần phải làm như vậy vì tôi có khả năng tạo ra nhiều kiểu product khác nhau, trong khi người ta xài cách của anh khi họ cần tạo ra một kiểu product nào đó thôi, vì thế anh không có cồng kềnh như tôi, anh chỉ cần một method duy nhất.:bbpnodo:

Nguyễn Thoại: Anh Abstract Factory bớt nóng, tôi nghe đồn rằng anh thường sử dụng nhiều hàm factory method theo cách của anh Factory Method để tạo các đổi tượng bên trong những factories của anh, điều đó có đúng ko?

Abstract Factory: Đúng đó em, anh thừa nhận điêu này. Những lớp factory con thường dùng các factory method để tạo các products tương ứng. Trong trường hợp này, các factory method được dùng thuần túy để tạo ra các products.

Factory Method: … còn tôi dùng hàm factory method để tạo ra product cụ thể mà người ta muốn, người dùng sẽ không biết cái gì được tạo ra, họ chỉ cần gọi hàm.

Nguyễn Thoại: Dường như hai anh làm rất tốt công việc của mình. Tôi chắc rằng đọc giả đã có được lựa chọn của mình. Sau cùng, những factories của 2 anh quả thật rất hữu ích, đọc giả của tôi sẽ sử dụng chúng trong các tình huống thích hợp nhất. Các anh đều đóng gói (encapsulate) quá trình tạo ra đối tượng để giúp chương trình độc lập và giảm phụ thuộc với những kiểu cụ thể, việc làm này thật đáng tuyên dương. Cám ơn hai anh, hai anh có lời gì trước khi chào tạm biệt đọc giả không ạ?:bbpbtay:

Abstract Factory: Cám ơn. Hãy nhớ đến tôi, Abstract Factory, và sử dụng tôi bất cứ khi nào bạn cần cùng một lúc tạo ra nhiều loại products, và khi bạn muốn chắc chắn những nơi sử dụng sẽ không cần biết đến những lớp cụ thể khi cần làm việc này.:bbpskien:

Factory Method: Còn tôi là Factory Method, hãy sử dụng tôi để làm cho chương trình của bạn độc lập với những lớp cụ thể mà bạn cần tạo 1 đối tượng, hoặc khi bạn không biết sau này sẽ cần đến những lớp con nào nữa. Khi cần sử dụng tôi, hãy tạo tạo ra subclass (1 factory implement 1 kiểu abstract) và implement factory method cho chính bạn.:bbpraroi:



(Page 158-162 of Head First – Design Pattern)



Abstract Factory and Factory Method (Design Patterns)





Dependency Injection with Spring.Net p1

(Bài viết dịch từ bài Dependency Injection with Spring.Net của David Consdorf, thêm hành thêm tiêu rồi nấu lại bởi Nguyễn Thoại :bbpraroi:)



Introduction:

- Spring.Net là một framework hỗ trợ nhiều chức năng cho những ứng dụng .NET. Phần nhân chính của Spring.Net là Dependency Injection hay còn được biết đến với tên gọi Inversion of Control(IoC). Tôi có bổ sung đoạn giới thiệu vui về 2 mẫu design pattern Factory. Ngoài ra, với những đoạn code mẫu mà tác giả cung cấp (ở các phần sau), hi vọng các bạn sẽ có một cái nhìn cơ bản về Spring.Net và có thể áp dụng nó cho những ứng dụng của mình.

Spring.Net: Overview

- Spring.Net là một framework nguồn mở cung cấp một tập các components giúp người lập trình áp dụng được những kĩ thuật nổi tiếng như Dependency Injection và Aspect-Oriented Programming. Bộ Spring.Net được chuyển từ phiên bản Java của Spring framework. Ngày nay, phiên bản Java của Spring đã được sử dụng rất thành công trong rất nhiều ứng dụng. Cùng với sự thành công của người anh em Spring Java, sự xuất thiện của Spring.Net chỉ là vấn đề thời gian. Thực sự như vậy, kể từ khi ra đời, Spring.Net đang chiếm được sự ủng hộ nhiệt tình của cộng đồng .NET

- Các chức năng của Spring.NET:

  • Dependency Injection
  • Aspect-Oriented Programming
  • Data access support including support for NHibenrate (ORM framework)
  • Web Framework
  • Integration Testing
  • Validation Framework
  • Dynamic Reflection
  • Threading and Concurrency Support
  • Object Pooling
  • Expression Evaluation
  • Services
  • Và nhiều chức năng khác...

- Cùng với sự đóng góp của cộng đồng, Spring.Net đang dần phát triển với nhiều chức năng mới đang được bổ sung thêm. Loạt bài viết này chỉ hi vọng truyền tải được chức năng thứ nhất cho các bạn. Chúng ta cũng cần lưu ý rằng Spring.Net cũng như một chiếc hộp gồm nhiều công cụ trong đó. Bạn không cần thiết phải sử dụng hết mọi thứ trong chiếc hộp này. Chúng ta có thể kết hợp một số chức năng và sử dụng những gì cần thiết cho ứng dụng của mình. Ngoài ra, Spring.Net còn được chia ra thành nhiều assemblies riêng và chúng ta không cần phải nhúng toàn bộ framework Spring vào chương trình.

Dependency Injection with a Factory Pattern

- Thành phần chính của Spring.Net là Dependency Injection(DI) còn được biết đến như Inversion of Control (IoC). Ý tưởng cơ bản của Dependency Injection là làm giảm sự phụ thuộc của những đối tượng (Objects) trong hệ thống. Dependency Injection cho người lập trình khả năng thiết kế những chương trình, trong đó các đối tượng (Objects) có thể tự thiết lập mối quan hệ đến những đối tượng khác mà nó cần. Thậm chí cho phép những tiến trình (processes) có sử dụng đối tượng làm công việc này. Mục tiêu chính của DI là hướng tới tính Loose Coupling, vì vậy nhóm những đối tượng (objects) nên làm việc độc lập với nhau, tập trung trên những behavior của chúng mà không cần biết những nhóm đối tượng khác (reference tới) sẽ làm việc như thế nào cũng như được thiết lập (construct) như thế nào.

- Để hiểu kĩ hơn về khái niệm Dependency Injection, chúng ta sẽ nhìn lại những thiết kế truyền thống của DI bằng cách sử dụng các lớp factory. Được mô tả kĩ trong các tài liệu Design Patternc có 2 mẫu thiết kế factory: Abstract Factory Pattern và Factory Method Pattern. Xin được sử dụng câu chuyện sau để giải thích cho dễ hiểu:


- Thị trường chứng khoán Việt Nam những tháng đầu năm 2008 vô cùng ảm đạm, tôi thấy mình đua đòi đầu tư chứng khoán vô những ngành bất động sản, tài chính không ổn chút nào. Trong khi đó tình hình lương thực thực phẩm trên thế giới vô cùng HOT. Sau nhiều ngày suy nghĩ,:bbpnghi:tôi quyết định đổ tiền đầu tư vô ngành thực phẩm bánh kẹo .Tôi sẽ mở một cơ sở sản xuất bánh. Trong nhóm sản phẩm bánh mì, tôi quyết định đầu tư làm bánh hambơgơ và bánh mì Sài Gòn đặc ruột thơm bơ :bbpraroi:. Như vậy phải mua máy để làm bánh, tôi vay họ hàng mua 2 cái máy sẽ làm ra 2 loại bánh trên, một máy chuyên để làm bánh mì Sài Gòn và một máy chuyên làm ra bánh hambơgơ, nhà máy của tôi sẽ thay phiên bật 2 máy đó vào các ngày chẳn và lẽ trong tuần để làm bánh, ngày nào cần làm bánh loại nào thì bật máy loại đó. Và sơ đồ nhà máy tôi như sau:


Abstract Factory Method

Hình 1: Abstract Factory Pattern

Bản thiết kế:



abstract class MayLamBanh
{
public static MayLamBanh ChonMayLamBanh()
{
bool ngayChan = KiemTraNgayChanLe();
if (ngayChan == true)
{
return new MayLamBanhhamburger();
}
else
{
return new MayLamBanhMiSaiGon();
}
}
public abstract Banh LamBanh();
}

class MayLamBanhhamburger : MayLamBanh {
public override Banh LamBanh() {
return new BanhHamburger();
}
}

class MayLamBanhMiSaiGon : MayLamBanh {
public override Banh LamBanh()
{
return new BanhMiSaiGon();
}
}

abstract class Banh {
}

class BanhHamburger : Banh {
}

class BanhMiSaiGon : Banh {
}

public class NhaMay {
public static void main(String[] args) {
MayLamBanh factory = MayLamBanh.ChonMayLamBanh();
Banh banh = factory.LamBanh();
}
}

- Như vậy khi áp dụng Abstract Factory Pattern là bạn tạo ra những lớp CFactory, tất cả những CFactory này sẽ implement cùng 1 interface IFactory, khi đó instance factory thuộc kiểu nào sẽ làm ra product tương ứng.

- Quay lại chuyện làm bánh, sau một thời gian tôi kiểm toán sổ sách và thấy rằng tiền lời không nhiều. Chi phí quản lý và bảo trì hai cái máy quá tốn kém trong khi đối thủ cạnh tranh thì ngày càng tạo ra sản phẩm đa dạng. Giờ nếu muốn làm ra sản phẩm bánh kem để cạnh tranh thì phải mua thêm máy khác vừa tốn kém lại tốn chi phí bảo trì. :bbpbuon: Tôi đọc báo Dân Trí và phát hiện rằng các chú kĩ sư cơ khí Việt Nam vừa chế ra một cái máy đa năng có thể tạo ra đủ loại bánh. Chỉ cần thêm vào công thức vào là máy có thể làm ra bánh theo ý muốn. Khi đó tuỳ tỉ lệ đường, tỉ lệ bột, tỉ lệ bột nở, tỉ lệ nước mà sẽ tạo ra loại bánh theo công thức. Tôi khoái quá, bán rẻ ngay 2 cái máy dỏm và vay thêm chút đỉnh mua cái máy đa năng đó về. Các chú kĩ sư cơ khí giao cho tôi bản thiết kế mới như sau:


Abstract Method Pattern

Hình 2: Factory Method Pattern

Bản thiết kế:


class MayLamBanhDaNang : MayLamBanh
{
public Banh LamBanh(double soLuongDuong, double soLuongBot, double soLitNuoc)
{
if (soLuongDuong / soLuongBot){
return new BanhHamburger();
}
else
{
return new BanhMiSaiGon();
}
}
}


- Nhờ và cái máy này, xưởng sản xuất của tôi ăn nên làm ra và chuẩn bị lên đời thành công ty cổ phần bánh kẹo nước giải khát BSG (Bánh Mỳ Sài Gòn) :bbpxtay:

- Như vậy Factory Method Pattern là mấu thiết kế mà bạn tạo ra một interface IFactory có khai báo hàm tạo ra những product (Object). Sau đó bạn để trách nhiệm tạo ra product loại nào cho lớp CFactory implement IFactory của bạn.

Define an interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.

- Tóm lại, factory là một hoặc nhiều đối tượng chịu trách nhiệm tạo ra những đối tượng khác mà chương trình sử dụng. Nói chung, ứng dụng sẽ không biết gì về cách tạo ra những đối tượng nó cần, thay vào đó nó chỉ nên biết đến những đối tượng đó thông qua 1 interface. Bằng cách đóng gói (encapsulation) những cài đặt (implementation) và thiết lập (construct) cho lớp trong factory, chương trình của chúng ta có thể sử dụng những gì nó cần mà không biết đối tượng cụ thể nào đang được gọi, đối tượng đó được tạo ra như thể nào cũng như những đối tượng đó làm gì.

- Trong những ứng dụng lớn với khả năng hỗ trợ nhiều thiết lập, cấu hình, factories còn có thể đóng vai trò như bộ phận trung tâm thực hiện việt thay đổi những cấu hình đó. Ví dụ, nếu bạn cần chuyển đổi nhiều database component truy xuất dữ liệu MySQL và thay thế chúng bằng những component mới truy xuất dữ liệu Oracle, tất cả những gì bạn cần làm là đổi lớp factory và chuyển nó sang những component Oracle. Phần còn lại của ứng dụng sẽ không bị ảnh hưởng, bởi vì tất cả những component database đều được cài đặt (implement) từ cùng 1 interface, gồm các hàm truy xuất, lưu cũng như cập nhật và xoá dữ liệu. Còn làm cách nào mà những component đó làm việc bên dưới và loại database nào mà chúng truy xuất thực sự không quan trọng.

-----------------------------------------------------------------------------------

:feel_good: Vậy trong cái nhà máy làm bánh củ chuối ở trên thì DI thể hiện ở chỗ nào? Dependency Injection ở điểm sau: thời còn 2 cái máy làm 2 loại bánh, tôi thích làm ra loại nào thì tôi xài cái máy ấy. Bây giờ bánh mì SàiGòn đặc ruột thơm bơ của tôi ế ẩm vì không cạnh tranh nổi với mấy người làm bánh mì bán dạo bằng xe đạp. Cho nên tôi muốn chuyển qua sản xuất thêm bánh bao. Tôi có thể thuê hoặc mua mới một cái máy làm bánh bao tự động về để ở một chỗ trong xưởng mà không cần phải đập xây lại nhà máy sản xuất, không cần tổ chức lại khâu đóng hộp phân phối. Tôi cũng chẳng cần phải bán đi cái máy làm bánh mì Sài Gòn vì biết đâu tương lai mấy cha bán bánh mì dạo đổi sang bán keo dính duột, lúc đấy thì bật lại máy làm bánh mì để đa dạng sản xuất. Nhưng kinh doanh quả là không đơn giản với những người hiền lành, nghe lời mấy bạn kĩ sư cơ khí mua cái máy đa năng làm bánh tôi mới ôm hận. Tuy cái máy đó làm được nhiều loại bánh nhưng tốc độ làm bánh vừa chậm lại còn hao điện, ngoài ra lượng hao hụt nguyên vật liệu quá lớn khiến giá thành sản phẩm quá cao không cạnh tranh nổi với Kinh Đô Bakery. Tôi lại mang tính chủ quan, nghĩ rằng với một cái máy này là đủ nên không có máy dự phòng. Bây giờ tôi muốn thay máy khác cũng phải đợi đến lúc có máy thì mới đưa vào sử dụng chứ không thể ngừng sản xuất. :bbpcuoi3:Tôi quyết định liều thuê đám kĩ sư chất lượng cao vừa tốt nghiệp đại học làm riêng cho tôi một cái máy dựa trên bản thiết kế ban đầu, làm sao cho ít hao điện và nguyên vật liệu, tốc độ làm bánh nhanh hơn. 1 tháng sau đó tôi đã có được cái máy mới như mong muốn, tôi thuê xe ôm chở máy vào xưởng đặt một chỗ thoáng mát, bật điện máy mới và shut down máy cũ. Thế là dây chuyền làm bánh của tôi chạy liên tục chỉ mất một chút thời gian bật tắt mà không phải ngừng sản xuất trong thời gian dài. Tuy vậy hệ thống của tôi vẫn có chút bất tiện. Như các bạn thấy lúc mới mở phân xưởng, tôi sử dụng 2 cái máy để làm bánh. Lúc cần làm bánh hambơgơ tôi phải vào phân sưởng tắt điện máy làm bánh mì và bật điện máy kia. Đến khi có cái máy đa năng, thình thoảng lại phải chạy đến xưởng để đổi công thức làm bánh. Thật là phiền khi chạy đi chạy lại, ngừng toàn nhà máy để thay đổi. Thật may lúc trước ở công ty cũ tôi có quen một tay rất rành về hệ thống mạng điều khiển từ xa, hắn tư vấn cho tôi một hệ thống gọi là Spring cài đặt nối mạng máy làm bánh với hệ thống máy tính, tôi chỉ cần ngồi ở nhà click chuột là nhà máy của tôi sẽ làm ra bánh khác mà không cần phải ngừng hoạt động hay khởi động lại dây chuyền hoặc chạy vô phân xưởng để đổi công thức. Bị lừa lần trước tôi không tin tưởng nên lên mạng google vài cú, và tôi tìm được thông tin rằng mấy tay sản xuất kẹo dừa bên Java Indonesia đã sử dụng hệ thống Spring bên đấy mấy năm nay rồi và rất thành công.


Phần 2

Phần 3

Phần 4

Phần 5

Phần 6

(Các bạn đang xem phần 1)

rss
 

About Me

Place I've live
Near Bossley Park, Sydney, NSW, Australia
Place I've work
  • Freelancer (from 06/2010 to present)
  • Harvey Nash (from 05/2008 to 06/2010)
  • DataDesign Vietnam (10/2005 to 04/2008)
Place I've studied
  • University of Natural Science (Bachelor of Science HoChiMinh City Vietnam From 2001 to 2005)
  • Le Hong Phong High School (HoChiMinh City Vietnam From 1997 to 2000)