2013-03-17 15 views
5

Tôi đã trải qua cuốn sách Java hiệu quả và tạo ghi chú cho tài liệu tham khảo trong tương lai của tôi, tôi đã xem qua Mẫu tạo hình.Mẫu Trình tạo: biến thể nào được ưa thích hơn?

Tôi hiểu nó là gì và cách giả sử nó được sử dụng như thế nào.Trong quá trình tôi tạo ra hai biến thể mẫu của mẫu trình xây dựng.

Tôi cần trợ giúp liệt kê những khác biệt và lợi thế của từng loại? Tôi chắc chắn nhận thấy rằng, Example 1 cho thấy ít phương pháp hơn, có ít hạn chế hơn và chung chung hơn, bằng cách cho phép nó được sử dụng linh hoạt hơn.

Hãy chỉ ra những thứ khác mà tôi đã bỏ lỡ?

Ví dụ 1

package item2; 

/** 
* @author Sudhakar Duraiswamy 
* 
*/ 
public class Vehicle { 

    private String type; 
    private int wheels; 

    interface Builder<T>{ 
     public T build(); 
    } 

    public static class CarBuilder implements Builder<Vehicle>{ 
     private String type; 
     private int wheels;  

     CarBuilder createVehicle(){ 
      this.type= "Car"; 
      return this; 
     } 

     CarBuilder addWheels(int wheels){ 
      this.wheels = wheels; 
      return this; 
     } 

     public Vehicle build(){ 
      Vehicle v = new Vehicle(); 
      v.type = type; 
      v.wheels = wheels; 
      return v; 
     }    
    } 

    public static class TruckBuilder implements Builder<Vehicle>{  
     private String type; 
     private int wheels; 

     TruckBuilder createVehicle(){   
      this.type= "Truck"; 
      return this; 
     } 

     TruckBuilder addWheels(int wheels){ 
      this.wheels = wheels; 
      return this; 
     } 

     public Vehicle build(){ 
      Vehicle v = new Vehicle(); 
      v.type = type; 
      v.wheels = wheels; 
      return v; 
     } 
    } 

    public Vehicle(){ 

    } 

    public static void main(String[] args) { 
     //This builds a car with 4 wheels 
     Vehicle car = new Vehicle.CarBuilder().createVehicle().addWheels(4).build(); 

     //THis builds a Truck with 10 wheels 
     Vehicle truck = new Vehicle.TruckBuilder().createVehicle().addWheels(10).build(); 

    } 
} 

Ví dụ 2

package item2; 
/** 
* @author Sudhakar Duraiswamy 
* 
*/ 
public class Vehicle2 { 

    private String type; 
    private int wheels; 

    interface Builder<T>{ 
     public T build();  
     public String getType(); 
     public int getWheels() ; 
    } 

    public static class CarBuilder implements Builder<Vehicle2>{ 
     private String type; 
     private int wheels;  

     public String getType() { 
      return type; 
     } 
     public int getWheels() { 
      return wheels; 
     } 

     CarBuilder createVehicle(){ 
      this.type= "Car"; 
      return this; 
     } 

     CarBuilder addWheels(int wheels){ 
      this.wheels = wheels; 
      return this; 
     } 

     public Vehicle2 build(){   
      return new Vehicle2(this); 
     }    
    } 

    public static class TruckBuilder implements Builder<Vehicle2>{  
     private String type; 
     private int wheels; 

     public String getType() { 
      return type; 
     } 

     public int getWheels() { 
      return wheels; 
     } 

     TruckBuilder createVehicle(){   
      this.type= "Truck"; 
      return this; 
     } 

     TruckBuilder addWheels(int wheels){ 
      this.wheels = wheels; 
      return this; 
     } 

     public Vehicle2 build(){ 
      return new Vehicle2(this); 
     } 
    } 


public Vehicle2(Builder<? extends Vehicle2> builder){ 
    Vehicle2 v = new Vehicle2(); 
    v.type = builder.getType(); 
    v.wheels = builder.getWheels(); 
} 

    public Vehicle2(){ 
    } 

    public static void main(String[] args) {    
     //This builds a car with 4 wheels 
     Vehicle2 car = new Vehicle2.CarBuilder().createVehicle().addWheels(4).build(); 

     //THis builds a Truck with 10 wheels 
     Vehicle2 truck = new Vehicle2.TruckBuilder().createVehicle().addWheels(10).build(); 
    } 
} 
+7

Nghiêm túc xuống bỏ phiếu mà không bình luận để lại là què – Sudhakar

+2

Guys, nếu bạn có thể để lại ý kiến ​​là tại sao câu hỏi này là không thích hợp, nó sẽ thực sự giúp tôi và những người khác – Sudhakar

+0

Bạn nên đi qua trang web này http: // en .wikipedia.org/wiki/Builder_pattern # Java để xem ví dụ thích hợp cho việc triển khai 'Trình tạo mẫu'. –

Trả lời

5

Không có mục nào ở trên.

Người đầu tiên không cho phép xây dựng một chiếc xe không thay đổi, thường là lý do tại sao mẫu Builder được sử dụng.

Ví dụ thứ hai là biến thể của mẫu đầu tiên cho phép nhận thông tin từ trình tạo bằng cách sử dụng các phương thức getter bổ sung. Nhưng những phương pháp đó không được sử dụng ở bất cứ đâu, ngoại trừ trong phương thức khởi tạo của Xe, có quyền truy cập trực tiếp vào các trường của trình tạo. Tôi không thấy điểm trong việc thêm chúng.

tôi thấy hai điều quan trọng hơn để cải thiện:

  1. Hai loại người xây dựng thực hiện chính xác những điều tương tự. Không cần hai loại. Một cái duy nhất là đủ.
  2. Phương thức createVehicle() nên được thực hiện bởi hàm tạo của trình tạo. Nếu bạn xây dựng một CarBuilder, nó rõ ràng là để xây dựng một chiếc xe, vì vậy các loại xe nên được thiết lập ngay sau khi xây dựng được xây dựng. Đây là cách tôi sẽ viết nó:

.

public final class Vehicle { 

    private final String type; 
    private final int wheels; 

    private Vehicle(Builder builder) { 
     this.type = builder.type; 
     this.wheels = builder.wheels; 
    } 

    public static Builder carBuilder() { 
     return new Builder("car"); 
    } 

    public static Builder truckBuilder() { 
     return new Builder("truck"); 
    } 

    public static class Builder { 
     private final String type; 
     private int wheels; 

     private Builder(String type) { 
      this.type = type; 
     } 

     public Builder addWheels(int wheels){ 
      this.wheels = wheels; 
      return this; 
     } 

     public Vehicle build() { 
      return new Vehicle(this); 
     }    
    } 

    public static void main(String[] args) { 
     Vehicle car = Vehicle.carBuilder().addWheels(4).build(); 
     Vehicle truck = Vehicle.truckBuilder().addWheels(10).build(); 
    } 
} 
+0

Cảm ơn bạn đã chỉ ra 'bất biến', tôi đoán thats là tôi đã nhận nó sai.Tôi nghĩ rằng mô hình xây dựng là chủ yếu được sử dụng để ẩn các bước liên quan đến xây dựng các đối tượng phức tạp, nhưng bất biến không phải là một yêu cầu bắt buộc. Đánh giá cao, bạn đã đăng với một example.cheers – Sudhakar

+0

JB Nizet: vì vậy nếu tôi giới thiệu 'final' cho các biến cá thể trong 'Example 1', thì nó sẽ tạo một BuilderPattern hợp lệ, đúng không? – Sudhakar

+0

Nếu bạn làm cho các trường cuối cùng, nó sẽ không biên dịch nữa, vì bạn đang cố sửa đổi giá trị của các trường từ trình tạo. Các nhà xây dựng của bạn * là các ví dụ về mẫu Builder. Nhưng cái đầu tiên không cho phép bất biến và có mã dự phòng, và mã thứ hai cũng có mã dự phòng. Cả hai đều có thể được cải thiện bằng cách sử dụng mã tôi đã thể hiện trong câu trả lời của tôi, đó là ngắn gọn hơn, an toàn hơn và cho phép bất biến. –

2

Có một biến thể thứ ba cũng vậy, với mã ít:

Thay vì có ví dụ của riêng họ các lĩnh vực các nhà xây dựng cũng có thể làm thay đổi trạng thái của Vehicle. lớp bên trong có thể viết thành viên private của lớp bên ngoài của họ:

class Vehicle { 
    private int wheels; 

    private Vehicle() {} 

    public static class Builder { 
    private boolean building = true; 
    private Vehicle vehicle = new Vehicle(); 

    public Builder buildWheels(int wheels) { 
     if(!this.building) throw new IllegalStateException(); 
     this.vehicle.wheels = wheels; 
     return this; 
    } 

    public Vehicle build() { 
     this.building = false; 
     return this.vehicle; 
    } 
    } 
} 

Kể từ khi các trường là tư nhân và bạn cho phép nó được xây dựng chỉ lần (building cờ), được xây dựng Vehicle trường vẫn còn bất biến cho người tiêu dùng thậm chí mặc dù các trường không thể là final nữa (không còn realio-trulio immutability, see Eric's blog article có trên C# nhưng các khái niệm tương tự).

Bạn cần phải cẩn thận hơn vì các trường không phải cuối cùng không phải được khởi tạo trong khi xây dựng đối tượng (được thực thi bởi trình biên dịch) và bạn phải kiểm tra cẩn thận trạng thái building. Tuy nhiên, bạn lưu toàn bộ bản sao của tất cả các trường mẫu. Nói chung, điều này rất hữu ích nếu bạn có một tập hợp các biến mẫu khá lớn được xây dựng với các phương thức khá ít, trong đó mỗi phương thức xây dựng một vài trường cùng một lúc.

Tôi biết điều này không chỉ ra bất kỳ lợi thế hoặc hạn chế nào trong các cách tiếp cận của bạn. Tuy nhiên, cách tiếp cận này có thể tiết kiệm rất nhiều mã bổ sung nếu bạn không cần các trường là final.

+0

Không, trường hợp 'Vechicle' không phải là bất biến; xem câu trả lời này: http://stackoverflow.com/a/6388762/262683 –

+0

@CostiCiudatu Cảm ơn bạn đã chỉ ra; Tôi bỏ qua cờ 'building' trong ví dụ ban đầu của tôi (đánh giá thấp tầm quan trọng của nó). Đã chỉnh sửa câu trả lời của tôi. –