Có bất kỳ ngôn ngữ lập trình hướng đối tượng nào hỗ trợ các nhà xây dựng tập thể khác không?


8

Gần đây tôi đã xem xét rằng đôi khi một số đối tượng phụ thuộc vào nhau (ví dụ: nếu chúng có chứa các tham chiếu theo chu kỳ) và do đó sẽ hữu ích khi tạo chúng như một phần của một hoạt động nguyên tử để đảm bảo rằng, sau khi xây dựng, các đối tượng mới thực hiện một số ràng buộc tập thể .

Để làm điều này, người ta có thể có các hàm tạo có thể tạo nhiều hơn một đối tượng. Các lập trình viên sau đó sẽ đưa vào một constructor đơn tất cả các mã đảm bảo rằng, một khi đối tượng o 1 , ..., o n đã được tạo ra, họ đáp ứng tất cả những hạn chế cần thiết (ví dụ như tất cả các liên kết giữa các đối tượng mới đã được tại chỗ). Bản thân tôi đã tạo ra thuật ngữ các nhà xây dựng tập thể bởi vì tôi chưa bao giờ nghe nói về một tính năng như vậy, nhưng có thể tồn tại một tên được chấp nhận cho khái niệm này.

Vì vậy, có ngôn ngữ lập trình nào hỗ trợ loại nhà xây dựng này không? Nếu không, ý tưởng đã được thử chưa?


3
Tôi không chắc, nhưng điều đầu tiên tôi nghĩ đến là factorymẫu.
JensG

3
Cử tri có thể giải thích về việc bỏ phiếu chặt chẽ? Tôi đang hỏi liệu có tồn tại một ngôn ngữ lập trình với một tính năng rất cụ thể không. Câu hỏi dường như không lạc đề hoặc có công thức kém đối với tôi nhưng tôi sẵn sàng phản hồi.
Giorgio

@JensG: Tôi đã nghĩ về điều đó, nhưng một nhà máy có một số hạn chế. Ví dụ: nếu một đối tượng chứa một tham chiếu bất biến, bạn không thể đặt nó trong một nhà máy: bạn chỉ có thể đặt nó trong hàm tạo. Tôi đang xem xét ngữ nghĩa Java ở đây, nhưng tôi nghĩ đây có thể là một vấn đề chung.
Giorgio

Điều này thật thú vị vì hiện tại tôi đang hack một thứ tương tự trong C # bằng cách sử dụng các bộ chứa IoC. Ngoài ra, điều này khác với các ngôn ngữ có đặc điểm như thế nào và cho phép những đặc điểm đó được trộn lẫn để lấp đầy các thành viên trừu tượng? Một ngôn ngữ đồ chơi tôi đã làm việc trên A with Bthành phần kiểu được hỗ trợ , mà người xây dựng kết quả của nó về cơ bản sẽ xây dựng kiểu mới bao gồm hai đặc điểm.
Telastyn

3
Câu hỏi này rõ ràng không phải là "yêu cầu chúng tôi đề xuất một công cụ, thư viện hoặc tài nguyên ngoài trang yêu thích" và thật xấu hổ cho trang web mà hai người đã bỏ phiếu để đóng nó khi làm như vậy. Tôi đã đọc lại tiêu đề một chút để làm cho điều này thậm chí còn rõ ràng hơn.
Carson63000

Câu trả lời:


12

Điều này nghe có vẻ giống như Mô hình Builder đối với tôi, đây là một dạng Nhà máy phức tạp hơn. Một ví dụ Java là StringBuilder mà bạn sử dụng để xây dựng Chuỗi, sau đó gọi builder.toString()khi bạn muốn kết quả không thay đổi. Tuy nhiên, bạn có thể sử dụng mẫu trình xây dựng để xây dựng các bộ sưu tập đối tượng không đồng nhất phức tạp hơn. Bạn có thể sử dụng friendngữ nghĩa trong một trình xây dựng để có quyền truy cập vào các biến riêng tư được coi là bất biến sau khi đối tượng kết quả được tạo.

Ngôn ngữ chức năng có thể cung cấp một số nguồn cảm hứng. Scala, ví dụ, có một ListBuffer có thể thay đổi có thể được sử dụng cho giai đoạn xây dựng, sau đó được chuyển đổi thành Danh sách bất biến .

Một khái niệm có thể có liên quan khác là Freezable Object , theo đó một đối tượng được coi là có thể thay đổi cho đến khi một Freeze()phương thức được gọi trên nó. Một người xây dựng có thể sử dụng các đối tượng không đóng băng, sau đó đóng băng chúng trước khi quay trở lại.


Tôi thấy ý tưởng về một mô hình xây dựng kết hợp với đối tượng freezable rất tốt. Nó không chính xác như những gì tôi đã nghĩ trong đầu nhưng nó giải quyết vấn đề của tôi mà không đưa ra một khái niệm đặc biệt mới, đó là IMO tốt.
Giorgio

1: Eric Lippert đã loạt các bài báo liên quan đối tượng bất biến và được gọi là một trong những biến thể của "Freezable" đối tượng Popsicle tính bất biến (thuật ngữ tìm kiếm thuận tiện để tìm các bài viết :)) - toàn bộ loạt có thể hữu ích để đọc nếu bạn là thành xây dựng bất biến phức tạp các đối tượng trong ngôn ngữ giống như C #.
Alexei Levenkov

4

Ruby, Smalltalk, Self, Drameak, v.v. không có nhà xây dựng, họ chỉ có một quy ước đặt tên cho các phương thức nhà máy (ví dụ như newtrong Ruby). Vì chúng chỉ là các phương thức tiêu chuẩn không có thật như bất kỳ phương thức nào khác, chúng có thể làm bất cứ điều gì chúng muốn, bao gồm phân bổ và khởi tạo nhiều đối tượng như chúng muốn. Vấn đề chính là các phương thức nhà máy như vậy trả về, theo quy ước, một đối tượng duy nhất là một thể hiện của lớp mà phương thức nhà máy được gọi. Tức là khi gọi Foo.newnó, bạn sẽ nhận được một đối tượng duy nhất là một thể hiện của Foo. Nhưng, với tài liệu đầy đủ, bạn có thể trả về một số cấu trúc (ví dụ Array:) của nhiều đối tượng mới.

Thí dụ:

class Foo
  def self.new
    new_foo = super

    new_bar = Bar.new
    new_bar.foo = new_foo

    new_foo.bar = new_bar

    return new_foo, new_bar
  end

  attr_accessor :bar
end

class Bar
  attr_accessor :foo
end

foo, bar = Foo.new

Trong ECMAScript, các hàm tạo chỉ là các thủ tục thông thường, hay đúng hơn, bất kỳ thủ tục nào cũng có thể được sử dụng như một hàm tạo chỉ bằng cách dán newtừ khóa vào trước nó. Một lần nữa, vì họ chỉ là thủ tục thông thường, họ có thể làm bất cứ điều gì họ muốn.


1

(ví dụ: nếu chúng chứa các tham chiếu theo chu kỳ) [...] Để thực hiện điều này, người ta có thể có các hàm tạo có thể tạo nhiều hơn một đối tượng. Sau đó, lập trình viên sẽ đưa vào một hàm tạo duy nhất tất cả các mã đảm bảo rằng, một khi các đối tượng o1, ..., đã được tạo,

Phụ thuộc tuần hoàn giữa các đối tượng? Sau đó, câu trả lời là "không sử dụng (chỉ) một nhà xây dựng", bởi vì các cuộc gọi phương thức tuần hoàn không có ý nghĩa gì. Thay vào đó, đây là một kịch bản cổ điển cho một số phương thức Factory .

Đây là một ví dụ (trong PHP) là một thứ ngớ ngẩn nhưng minh họa ý tưởng chung: Bạn không thể tạo một cái Sprocketmà không có liên kết Widgetvà ngược lại. Mỗi đối tượng có một tham chiếu đến đối tượng khác khi nó trở nên có sẵn.

class Widget {            
    protected $sprocket = null;
    public function getSprocket(){ return $this->sprocket; }

    protected function __construct(){ 
        // Constructor cannot be called from outside, not public
        // Initialize self, to a limited degree
    }
    public static function create(Sprocket $partner=null){
        $me = new Widget(); // Can call constructor from same class

        // Here we can make all sorts of changes and additions and other
        // objects, wiring them all together, before revealing the result
        // to the outside world.

        if($partner !== null){
            $me->sprocket = $partner;

        }else{
            $me->sprocket = Sprocket::create($me);
        }
        return $me;
    }

}

/* 
 * Practically identical to Widget, just with some renaming
 */
class Sprocket {
    protected $widget = null;
    public function getWidget(){ return $this->widget; }

    protected function __construct(){  }
    public static function create(Widget $partner=null){            
        $me = new Sprocket();            
        if($partner !== null){
            $me->widget = $partner;
        }else{
            $me->widget = Widget::create($me);
        }
        return $me;
    }        
}

/* 
$mw = new Widget(); // NOT ALLOWED! Constructor not public
*/

$w = Widget::create(); // OK to call
$s = $w->getSprocket();
$w2 = $s->getWidget();

assert($w == $w2);

Nếu tôi phải làm điều này trong PHP 5.2 ngoài đời thực, tôi chỉ cần để công khai các hàm tạo và bảo mọi người không sử dụng chúng . Thay vào đó tôi có một makeWidgetWithSprocket()chức năng. Nếu ngôn ngữ là Java, tôi sẽ sử dụng các điều khiển khả năng hiển thị ở cấp độ gói để tránh thêm lỗi.

Đọc thêm:

  • Nếu bạn muốn chuyển nhiều tùy chọn và cài đặt cho create(), hãy xem xét mẫu Builder .
  • Nếu bạn thấy mình cần rất nhiều sự linh hoạt để sắp xếp lại mọi thứ theo nhiều cách khác nhau, hãy xem Inversion of Control framework, thường sử dụng (nhưng không phải luôn luôn) sử dụng phép nội xạ phụ thuộc để kết nối các đối tượng với nhau "từ bên ngoài".
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.