Trước tiên, chúng ta hãy cùng cafedev giới thiệu mọi thứ về Builder Design Pattern và phần code ví dụ chi tiết nhằm giúp ace dễ hiểu khi áp dụng trên các ngôn ngữ khác nhau. Ace có thể tham khảo thêm các bài khác tại series Design Pattern tại đây.
Pattern Builder nhằm mục đích “Tách biệt việc xây dựng một đối tượng phức tạp khỏi biểu diễn của nó để cùng một quá trình xây dựng có thể tạo ra các biểu diễn khác nhau.” Nó được sử dụng để xây dựng một đối tượng phức tạp theo từng bước và bước cuối cùng sẽ trả về đối tượng. Quá trình xây dựng một đối tượng nên chung chung để nó có thể được sử dụng để tạo ra các biểu diễn khác nhau của cùng một đối tượng.
Nội dung chính
1. Sơ đồ UML của Mẫu thiết kế trình xây dựng
- Sản phẩm(Product) – Lớp sản phẩm xác định loại đối tượng phức tạp sẽ được tạo bởi mẫu trình tạo.
- Builder – Lớp cơ sở trừu tượng này xác định tất cả các bước phải thực hiện để tạo ra một sản phẩm một cách chính xác. Mỗi bước thường trừu tượng vì chức năng thực tế của trình xây dựng được thực hiện trong các lớp con cụ thể. Phương thức GetProduct được sử dụng để trả về sản phẩm cuối cùng. Lớp người xây dựng thường được thay thế bằng một giao diện đơn giản.
- ConcreteBuilder – Có thể có bất kỳ số lớp nào của lớp xây dựng cụ thể kế thừa từ Builder. Các lớp này chứa các chức năng để tạo ra một sản phẩm phức tạp cụ thể.
- Director – Lớp giám đốc điều khiển thuật toán tạo ra đối tượng sản phẩm cuối cùng. Một đối tượng Director được khởi tạo và phương thức Construct của nó được gọi. Phương thức bao gồm một tham số để nắm bắt đối tượng cụ thể của người xây dựng bê tông sẽ được sử dụng để tạo ra sản phẩm. Sau đó, giám đốc gọi các phương thức của người xây dựng bê tông theo đúng thứ tự để tạo ra đối tượng sản phẩm. Khi hoàn tất quá trình, phương thức GetProduct của đối tượng người xây dựng có thể được sử dụng để trả lại sản phẩm.
2. Hãy xem Ví dụ về Mẫu Thiết kế Trình xây dựng:
Xem xét việc xây dựng một ngôi nhà. Nhà là sản phẩm cuối cùng (đối tượng) được trả lại như đầu ra của quá trình xây dựng. Nó sẽ có nhiều bước như thi công tầng hầm, xây tường và thi công mái nhà cũng vậy. Cuối cùng toàn bộ đồ vật nhà được trả lại. Ở đây bằng cách sử dụng cùng một quy trình, bạn có thể xây dựng những ngôi nhà với các thuộc tính khác nhau.
interface HousePlan
{
public void setBasement(String basement);
public void setStructure(String structure);
public void setRoof(String roof);
public void setInterior(String interior);
}
class House implements HousePlan
{
private String basement;
private String structure;
private String roof;
private String interior;
public void setBasement(String basement)
{
this.basement = basement;
}
public void setStructure(String structure)
{
this.structure = structure;
}
public void setRoof(String roof)
{
this.roof = roof;
}
public void setInterior(String interior)
{
this.interior = interior;
}
}
interface HouseBuilder
{
public void buildBasement();
public void buildStructure();
public void bulidRoof();
public void buildInterior();
public House getHouse();
}
class IglooHouseBuilder implements HouseBuilder
{
private House house;
public IglooHouseBuilder()
{
this.house = new House();
}
public void buildBasement()
{
house.setBasement("Ice Bars");
}
public void buildStructure()
{
house.setStructure("Ice Blocks");
}
public void buildInterior()
{
house.setInterior("Ice Carvings");
}
public void bulidRoof()
{
house.setRoof("Ice Dome");
}
public House getHouse()
{
return this.house;
}
}
class TipiHouseBuilder implements HouseBuilder
{
private House house;
public TipiHouseBuilder()
{
this.house = new House();
}
public void buildBasement()
{
house.setBasement("Wooden Poles");
}
public void buildStructure()
{
house.setStructure("Wood and Ice");
}
public void buildInterior()
{
house.setInterior("Fire Wood");
}
public void bulidRoof()
{
house.setRoof("Wood, caribou and seal skins");
}
public House getHouse()
{
return this.house;
}
}
class CivilEngineer
{
private HouseBuilder houseBuilder;
public CivilEngineer(HouseBuilder houseBuilder)
{
this.houseBuilder = houseBuilder;
}
public House getHouse()
{
return this.houseBuilder.getHouse();
}
public void constructHouse()
{
this.houseBuilder.buildBasement();
this.houseBuilder.buildStructure();
this.houseBuilder.bulidRoof();
this.houseBuilder.buildInterior();
}
}
class Builder
{
public static void main(String[] args)
{
HouseBuilder iglooBuilder = new IglooHouseBuilder();
CivilEngineer engineer = new CivilEngineer(iglooBuilder);
engineer.constructHouse();
House house = engineer.getHouse();
System.out.println("Builder constructed: "+ house);
}
}
Đầu ra:
Builder constructed: House@6d06d69c
3. Ưu điểm của Builder Design Pattern
- Các tham số cho hàm tạo được giảm bớt và được cung cấp trong các lệnh gọi phương thức rất dễ đọc.
- Builder Design Pattern cũng giúp giảm thiểu số lượng tham số trong phương thức khởi tạo và do đó không cần phải chuyển giá trị null cho các tham số tùy chọn cho phương thức khởi tạo.
- Đối tượng luôn được khởi tạo ở trạng thái hoàn chỉnh
- Các đối tượng bất biến có thể được xây dựng mà không cần nhiều logic phức tạp trong quá trình xây dựng đối tượng.
4. Nhược điểm của Builder Design Pattern
- Số lượng dòng mã tăng ít nhất lên gấp đôi trong mô hình trình tạo, nhưng nỗ lực được đền đáp về mặt thiết kế linh hoạt và mã dễ đọc hơn nhiều.
- Yêu cầu tạo một ConcreteBuilder riêng cho từng loại Sản phẩm khác nhau.
Cài ứng dụng cafedev để dễ dàng cập nhật tin và học lập trình mọi lúc mọi nơi tại đây.
Tài liệu từ cafedev:
- Full series tự học Design Pattern từ cơ bản tới nâng cao tại đây nha.
- Các nguồn kiến thức MIỄN PHÍ VÔ GIÁ từ cafedev tại đây
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng!