So sánh abstract factory và factory năm 2024

Giả sử như bạn cần mua một chiếc máy tính, nhưng bạn vẫn chưa quyết định được nên sử dụng máy tính của hãng nào. Ngoài kia bao la bạt ngàn những thương hiệu chất lượng cao như Apple, Lenovo, Asus, HP… Như vậy để có thể chọn được chiếc máy tính ưng ý, bạn sẽ có 2 cách sau:

– Đến showroom của từng hãng, rồi tham khảo từng máy. Bạn đi hết showroom của hãng này tới showroom của hãng khác để xem, rồi nhớ thông tin trong đầu để so sánh chiếc này hợp hơn, chiếc kia rẻ hơn …

So sánh abstract factory và factory năm 2024

– Bạn đến một cửa hàng bày bán tất cả các loại laptop của tất cả các hãng, rồi bạn hỏi tư vấn là với số tiền này, bạn có thể chọn được laptop loại nào. Hay bạn đang muốn xem thử máy của hãng A, bạn nhờ tư vấn viên mang ra giúp bạn một chiếc. Rồi bạn băn khoăn một chiếc của hãng B, bạn lại nhờ tư vấn viên mang ra một chiếc khác.

So sánh abstract factory và factory năm 2024

Rõ ràng là cách thứ hai tiết kiệm thời gian và công sức cho bạn rất nhiều. Đây chính là cách mà mẫu thiết kế Factory hoạt động.

Mẫu thiết kế factory là gì?

Factory pattern là một mẫu thiết kế thuộc nhóm Khởi tạo. Pattern này sử dụng một interface hay một abstract class mà tất cả các lớp chúng ta cần khởi tạo đối tượng sẽ kế thừa. Factory sẽ định nghĩa việc khởi tạo đối tượng, nhưng đối tượng nào sẽ được tạo thì phụ thuộc vào các lớp con. Do vậy, pattern này còn được gọi với cái tên Virtual Constructor (phương thức khởi tạo ảo).

Factory pattern mang lại những tác dụng:

– Tạo ra một cách khởi tạo object mới

– Che giấu quá trình xử lý logic của phương thức khởi tạo

– Giảm sự phụ thuộc, dễ dàng mở rộng trong trường hợp chưa biết chắc số lượng đối tượng là đã đủ hay chưa. Trong trường hợp chúng ta có thêm lớp con kế thừa Factory, việc gọi đến virtual constructor vẫn không hề thay đổi.

– Giảm khả năng gây lỗi compile, trong trường hợp chúng ta cần tạo một đối tượng mà quên khai báo lớp, chúng ta cũng có thể xử lý lỗi trong Factory và khai báo lớp cho chúng sau.

Cấu trúc của Factory pattern

Xét theo ví dụ ở đầu bài viết, Factory pattern sẽ có cấu trúc dạng như sau:

So sánh abstract factory và factory năm 2024

Các lớp con Lenovo, Asus, HP đều override lại phương thức getSpec từ interface Computer. Phương thức viewComputer() của client sẽ gọi tới phương thức viewComputer của lớp ComputerFactory và truyền vào đó một tham số computerBrand, chính là tên của máy tính mà client muốn xem thêm, để tạo một đối tượng tương ứng. Đối tượng này sẽ được sử dụng để chạy phương thức view mà lớp con đã override lại.

Factory pattern trong Java

Trong ví dụ trên, nếu chúng ta làm theo cách 1, mã nguồn sẽ có dạng như sau: undefined public class Client { public void viewComputer() {

public void ViewLenovo() {  
  Lenovo lenovoComputer = new Lenovo();  
  System.out.println(lenovoComputer.getSpec());  
}
public void ViewAsus() {  
  Asus asusComputer = new Asus();  
  System.out.println(asusComputer.getSpec());  
}
public void ViewHP() {  
  HP hpComputer = new HP();  
  System.out.println(hpComputer.getSpec());  
}  
} }undefined

Như vậy, client sẽ phải gọi đến từng constructor cụ thể của từng lớp để tạo được đối tượng mong muốn.

Vậy khi áp dụng Factory pattern, mã nguồn sẽ thế nào?

Bước 1: Xây dựng lớp factory: undefined public class ComputerFactory { public void viewComputer(String computerBrand) {

Computer computer;  
switch (computerBrand) {  
  case "Lenovo":  
    computer = new Lenovo();  
    break;  
  case "Asus":  
    computer = new Asus();  
    break;  
  case "HP":  
    computer = new HP();  
    break;  
  default:  
    System.out.println("Computer brand not found");  
    break;  
}  
if (computer != null) {  
  System.out.println(computer.getSpec());  
}  
} } undefined

Bước 2: Từ lớp client, chúng ta gửi chỉ thị đến Factory: undefined public class Client { public void viewComputer() {

ComputerFactory computerFactory = new ComputerFactory();  
computerFactory.viewComputer("Lenovo");  
computerFactory.viewComputer("HP");  
computerFactory.viewComputer("Asus");  
computerFactory.viewComputer("Dell");  
} } undefined

Như vậy, việc khởi tạo các đối tượng thuộc từng lớp kế thừa interface Computer đã bị ẩn đi đối với client. Mặt khác, khi chúng ta thêm mới lớp kế thừa Computer, chỉ có virtual constructor trong Factory cần cập nhật, thay vì phải thay đổi trên cả lớp Client.

In this tutorial, we’ll discuss the Factory pattern and all its flavors. This is a widely used pattern with its version for each specific problem. There are two main types of the Factory pattern, the Factory pattern itself and the Abstract Factory pattern. They are closely related and have similar goals.

Additionally, we have a simplified version of this pattern, which is often considered an idiom. However, it is important to discuss it in the context of the Factory pattern to understand the differences and applications.

Let’s start with the simplest version of the Factory pattern: the Factory Method. We want to use this idiom for two reasons: the single responsibility principle and code duplication. If the code for creation and picking an implementation is in our business logic, this breaks the single responsibility principle. Moving the instantiation logic to a separate method or class makes the code cleaner.

Another reason for using this idiom is to avoid code duplication. Keeping the code that creates an object consistent throughout our code base is a good idea. This also would provide a convenient way to change it in one place. Technically, the object itself can contain a method for convenient construction:

So sánh abstract factory và factory năm 2024

However, it is possible to create a dedicated class for this:

So sánh abstract factory và factory năm 2024

This can be implemented by moving the code to a separate method or a class. Because it just uses the principles of a clean code and doesn’t create a hierarchy of Factories, this is considered a programming idiom. Technically, having several Factories without a common interface would still be considered an idiom, especially if the logic is associated with a class instead of an object:

So sánh abstract factory và factory năm 2024

This technique is helpful for simple cases when one Factory is sufficient or runtime polymorphism isn’t required.

3. Factory Pattern

The Factory pattern is similar to the Template pattern. However, it creates an object rather than containing business logic. The main difference from the previous idiom is that this pattern uses polymorphism:

So sánh abstract factory và factory năm 2024

This pattern serves two goals, allowing a convenient way to change the Factory and create an object. Also, it encapsulates the creation of common objects. Additionally, the Factories can accept parameters to be very flexible in object creation and behave like a wrapper over constructors:

So sánh abstract factory và factory năm 2024

In the example above, a Factory produces various products based on the passed parameter. While we use a simple value as a parameter, it might be more complex and represented by a dedicated class.

4. Abstract Factory Pattern

The primary purpose of the Abstract Factory is to create an entire family the objects that aren’t in the same hierarchy. Creating UI elements for different styles or different models of furniture that would stylistically fit each other are good examples of this pattern:

So sánh abstract factory và factory năm 2024

Imagine that we’d like to create different furniture sets and ensure each piece fits the set:

So sánh abstract factory và factory năm 2024

One Factory is responsible for creating all the products in a set. This way, by providing an application with a Factory, we can ensure that the sets aren’t mixed up. Also, it allows changing the implementations of the products in the entire application by just switching the Factory implementation.

5. Abstract Factory vs. Parametrized Factory

Two Factory versions are often confused: Abstract Factory and Parametrized Factory. The reason is that both of them produce a set of different products. Usually, Parametrized Factory creates products that differ by state, but it could provide a different implementation.

The Abstract Factory produces a set of related but, at the same time, different products. In terms of object-oriented design, it means that the products would have different interfaces. This was the case for the example with the furniture Factory above. Let’s try to turn a Parametrized Factory into an Abstract Factory:

So sánh abstract factory và factory năm 2024

Although we are creating different types of ice cream, we use the same interface for all of them. This means that the difference is hidden from the user and insignificant to the interaction with the object. The Parametrized Factory was sufficient for the case, and the Abstract Factory is an overly complex solution to this problem.

However, if these types of ice cream had significant differences in their interfaces and behavior, which we should highlight for a client, the Abstract Factory would be a good fit for it. In this case, the structure would look like this, similar to the example with a furniture Factory above:

So sánh abstract factory và factory năm 2024

This logic can also work the other way around. We can consider a context where we can use our furniture pieces on the same interface, for example, in the context of transportation. This would mean that we can turn our initial Abstract Factory into Parametrized Factory only because we don’t need the products to have different interfaces:

So sánh abstract factory và factory năm 2024

While choosing the correct pattern, we should consider the products and the context where they’ll be used. Thus, the Abstract Factory is used where we need to have the differences between products explicit, and the Parametrized Factory is where it isn’t necessary.

6. Conclusion

In this article, we learned the differences between the Factory Method, the Factory, and the Abstract Factory. The Factory Method is a great tool to clean up the code and keep it simple. The Factory helps us to leverage polymorphism and be prepared for future changes. On top of the previous benefits, the Abstract Factory ensures that we are working with the set of related objects.

These similar techniques have slightly different goals and shouldn’t be confused. The patterns can make the code less complicated, more flexible, and more understandable for everyone working on it. However, it takes time to understand their application and where each would be more useful.