close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

Python Design Patterns: Prototype (Clone)

Prototype là một mẫu thiết kế khởi tạo cho phép sao chép các đối tượng, ngay cả những đối tượng phức tạp, mà không cần ghép nối với các lớp cụ thể của chúng.

Tất cả các lớp prototype phải có một giao diện chung để có thể sao chép các đối tượng ngay cả khi các lớp cụ thể của chúng là không xác định. Các đối tượng prototype có thể tạo ra các bản sao đầy đủ vì các đối tượng của cùng một lớp có thể truy cập vào các trường riêng tư của nhau.

Cách sử dụng mẫu

Sử dụng: Mẫu Prototype có sẵn trong Python với giao diện có thể sao chép Cloneable.

Nhận biết: Prototype có thể dễ dàng nhận ra bằng phương thức clone hoặc copy, v.v.

Chương trình minh họa

Ví dụ này minh họa cấu trúc của mẫu thiết kế Prototype. Nó tập trung vào việc trả lời những câu hỏi sau:

  • Nó bao gồm những lớp nào?
  • Các lớp này có vai trò gì?
  • Các thành phần của mẫu có liên quan với nhau theo cách nào?

main.py

import copy
class SelfReferencingEntity:
    def __init__(self):
        self.parent = None
    def set_parent(self, parent):
        self.parent = parent
class SomeComponent:
    """
    Python cung cấp giao diện Prototype của riêng nó thông qua các hàm 
    'copy.copy' và 'copy.deepcopy'. Và bất kỳ lớp nào muốn triển khai các 
    tùy chỉnh phải ghi đè các hàm thành viên '__copy__' và '__deepcopy__'.
    """
    def __init__(self, some_int, some_list_of_objects, some_circular_ref):
        self.some_int = some_int
        self.some_list_of_objects = some_list_of_objects
        self.some_circular_ref = some_circular_ref
    def __copy__(self):
        """
        Tạo một bản sao nông. Phương thức này sẽ được gọi bất cứ khi nào
         ai đó gọi 'copy.copy' với đối tượng này và giá trị được trả về dưới 
        dạng bản sao nông mới.
        """
        # Đầu tiên, hãy tạo bản sao của các đối tượng lồng nhau.
        some_list_of_objects = copy.copy(self.some_list_of_objects)
        some_circular_ref = copy.copy(self.some_circular_ref)
        # Sau đó, hãy nhân bản chính đối tượng, sử dụng các bản sao
        # được chuẩn bị của các đối tượng lồng nhau.
        new = self.__class__(
            self.some_int, some_list_of_objects, some_circular_ref
        )
        new.__dict__.update(self.__dict__)
        return new
    def __deepcopy__(self, memo={}):
        """
        Tạo một bản sao sâu. Phương thức này sẽ được gọi bất cứ khi nào ai đó gọi 
        'copy.deepcopy' với đối tượng này và giá trị trả về được trả về dưới dạng bản 
        sao sâu mới.
        Việc sử dụng đối số 'memo' là gì? Memo là từ điển được thư viện 'deepcopy' 
        sử dụng để ngăn các bản sao đệ quy vô hạn trong các trường hợp tham chiếu 
        vòng tròn. Truyền nó cho tất cả các lệnh gọi 'deepcopy' bạn thực hiện trong 
        quá trình triển khai '__deepcopy__' để ngăn việc đệ quy vô hạn.
        """
        # Đầu tiên, hãy tạo bản sao của các đối tượng lồng nhau.
        some_list_of_objects = copy.deepcopy(self.some_list_of_objects, memo)
        some_circular_ref = copy.deepcopy(self.some_circular_ref, memo)
        # Sau đó, hãy nhân bản chính đối tượng, sử dụng các bản sao
        # được chuẩn bị của các đối tượng lồng nhau.
        new = self.__class__(
            self.some_int, some_list_of_objects, some_circular_ref
        )
        new.__dict__ = copy.deepcopy(self.__dict__, memo)
        return new
if __name__ == "__main__":
    list_of_objects = [1, {1, 2, 3}, [1, 2, 3]]
    circular_ref = SelfReferencingEntity()
    component = SomeComponent(23, list_of_objects, circular_ref)
    circular_ref.set_parent(component)
    shallow_copied_component = copy.copy(component)
    # Hãy thay đổi danh sách trong shallow_copied_component  và xem 
    # nó có thay đổi trong component hay không.
    shallow_copied_component.some_list_of_objects.append("another object")
    if component.some_list_of_objects[-1] == "another object":
        print(
            "Adding elements to shallow_copied_component's "
            "some_list_of_objects adds it to component's "
            "some_list_of_objects."
        )
    else:
        print(
            "Adding elements to shallow_copied_component's "
            "some_list_of_objects doesn't add it to component's "
            "some_list_of_objects."
        )
    # Hãy thay đổi tập hợp trong danh sách các đối tượng.
    component.some_list_of_objects[1].add(4)
    if 4 in shallow_copied_component.some_list_of_objects[1]:
        print(
            "Changing objects in the component's some_list_of_objects "
            "changes that object in shallow_copied_component's "
            "some_list_of_objects."
        )
    else:
        print(
            "Changing objects in the component's some_list_of_objects "
            "doesn't change that object in shallow_copied_component's "
            "some_list_of_objects."
        )
    deep_copied_component = copy.deepcopy(component)
    # Hãy thay đổi danh sách trong deep_copied_component và xem 
    # nó có thay đổi trong component hay không.
    deep_copied_component.some_list_of_objects.append("one more object")
    if component.some_list_of_objects[-1] == "one more object":
        print(
            "Adding elements to deep_copied_component's "
            "some_list_of_objects adds it to component's "
            "some_list_of_objects."
        )
    else:
        print(
            "Adding elements to deep_copied_component's "
            "some_list_of_objects doesn't add it to component's "
            "some_list_of_objects."
        )
    # Hãy thay đổi tập hợp trong danh sách các đối tượng.
    component.some_list_of_objects[1].add(10)
    if 10 in deep_copied_component.some_list_of_objects[1]:
        print(
            "Changing objects in the component's some_list_of_objects "
            "changes that object in deep_copied_component's "
            "some_list_of_objects."
        )
    else:
        print(
            "Changing objects in the component's some_list_of_objects "
            "doesn't change that object in deep_copied_component's "
            "some_list_of_objects."
        )
    print(
        f"id(deep_copied_component.some_circular_ref.parent): "
        f"{id(deep_copied_component.some_circular_ref.parent)}"
    )
    print(
        f"id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent): "
        f"{id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent)}"
    )
    print(
        "^^ This shows that deepcopied objects contain same reference, they "
        "are not cloned repeatedly."
    )

Kết quả:

Adding elements to shallow_copied_component's some_list_of_objects adds it to component's some_list_of_objects.
Changing objects in the component's some_list_of_objects changes that object in shallow_copied_component's some_list_of_objects.
Adding elements to deep_copied_component's some_list_of_objects doesn't add it to component's some_list_of_objects.
Changing objects in the component's some_list_of_objects doesn't change that object in deep_copied_component's some_list_of_objects.
id(deep_copied_component.some_circular_ref.parent): 4429472784
id(deep_copied_component.some_circular_ref.parent.some_circular_ref.parent): 4429472784
^^ This shows that deepcopied objects contain same reference, they are not cloned repeatedly.

Đã đăng vào

trong

,

bởi

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *