Design Pattern: The Prototype Pattern

Giới thiệu

Prototype Pattern là một trong những pattern thông dụng trong lập trình hướng đối tượng, là một pattern thuộc nhóm Creational Patterns. Sáng tạo đó là một thiết kế pattern đặc biệt có liên quan tới việc khởi tạo Object, thay vì tạo nên Object, Prototype pattern sử dụng việc cloning (sao chép nguyên mẫu của Object). Nếu việc tạo nên Object lớn & tốn nhiều tài nguyên, bạn hãy nên sử dụng prototype patern.

Sáng tạo

Tất cả chúng ta được phân phối một Object & dùng chính Object này như là một hình tượng (template) khi cần tạo đối tượng mới. Việc tạo một Object mới sẽ dựa theo Object mẫu mà không sử dụng toán tử new hay constructor được phân phối bởi ngôn từ lập trình. Lý do là do tất cả chúng ta không hiểu rằng thông tin nội tại bên trong Object & có thể Object bị ẩn giấu thông tin chỉ phân phối ra bên ngoài một lượng thông tin hạn chế. Chính vì vậy chẳng thể dùng toán tử new & copy những dữ liệu được Object phân phối (vốn không đầy đủ) cho một Object mới. Cách hiệu quả nhất là để Object “mẫu” tự xác nhận thông tin & dữ liệu copy.

Sử dụng

Tránh việc tạo nhiều lớp con cho mỗi đối tượng tạo như của Abstract Factory Pattern.
Giảm ngân sách để tạo nên một đối tượng mới theo “chuẩn”, tức là việc này tăng Performance đối với việc sử dụng keyword new để tạo đối tượng mới.
Để seting Prototype Pattern, tạo nên một Clone() Method ở lớp cha, & triển khai ở các lớp con.
Cách nhân bản trong Prototype có 2 kiểu:

  • Shallow sao chép: chỉ nhân bản được value type.
  • Deep sao chép: nhân bản được value type & reference type.

<Đọc thêm shallow clone & Deep clone trong Java Difference between Deep and Shallow Sao chép in Java Object CloningExplanation of Deep and Shallow CopyingCloning in java using clone- Shallow and deep sao chép – 8 techniques for deep copying- 8 important points about cloning>

Xem Thêm  Cách tạo nền gradient màu bằng CSS và HTML - gradient nền trong html

Prototype pattern sẽ sử dụng những abstract class, class diagram dưới đây chỉ có 3 loại & khiến cho việc thực hiện không quá khó dàng.

Những class gia nhập vào prototype pattern bao gồm :

  • Prototype: Phân phối Interface hoặc Abstract Class để sao chép chính bản thân nó – phương pháp Clone().
  • ConcreatePrototype: Implement interface được phân phối bởi Prototype để sao chép chính bản thân nó. – Trổ tài rõ ràng phương pháp Clone().
  • Client: Tạo một object mới bằng cách yêu cầu prototype sao chép chính bản thân nó.

Ưu & điểm yếu

Prototype ẩn đi những lớp con rời rạc từ phía client, thành ra làm giảm đi số lớp con mà client cần biết. Không chỉ có thế pattern này khiến cho client hoạt động với những lớp con rõ ràng mà không phải biến đổi gì.
Sau đây là một vài lợi nhuận khác của prototype pattern:

  • Thêm & loại bỏ lớp concrete lúc run-time: Prototype thống nhất tiến trình khởi tạo một object mới vào trong hệ thống dễ dàng chỉ bằng cách đăng ký một thực thể nguyên mẫu với client. Điều đó linh hoạt hơn một tí đối với các mẫu kiến tạo khác bởi vì client có thể seting & loại bỏ các nguyên mẫu tại thời điểm run-time.
  • Khởi tạo object mới bằng cách biến đổi một vài attribute của object (các object có ít điểm nổi bật nhau): Một hệ thống linh hoạt sẽ để cho tất cả chúng ta tự define một hành động nào đó thông qua sự kết phù hợp với một object (nghĩa là một phương pháp của một class) hơn là define một class mới. Client có thể trổ tài một ảnh hưởng khác bằng cách ủy quyền cho lớp prototype. Cùng lúc mẹo khởi tạo này cũng giúp cho tất cả chúng ta khai báo một “lớp mới” mà không phải lập trình gì cả. Thực tiễn thì việc sao chép một nguyên mẫu giống như việc khởi tạo một object từ một class mới. Prototype pattern giúp giảm số lớp mà hệ thống cần dùng.
  • Khởi tạo object mới bằng cách biến đổi cấu tạo: Rất là nhiều áp dụng xây dựng hệ thống từ nhiều phần & các phần con. Các phần con lại khởi tạo từ nhiều phần con khác (chia nhỏ bài toán). Prototype pattern cũng suport điều này. Nghĩa là các phần đó có thể được khởi tạo từ việc sao chép một nguyên mẫu từ một “cấu trúc” khác. Miễn là các phần phối hợp đều trổ tài Clone() & được sử dụng với cấu tạo khác nhau làm nguyên mẫu.
  • Giảm việc phân lớp: Thỉnh thoảng hệ thống quá cầu kỳ vì có quá nhiều class, & cây thừa kế của lớp khởi tạo có quá nhiều lớp cùng lúc cùng mức. Prototype pattern rõ ràng và cụ thể làm giảm số lớp & sự cầu kỳ của cây thừa kế (class hierarchy). 1 điểm giới hạn của prototype pattern là thỉnh thoảng việc phải implement mỗi phương pháp Clone() của mỗi lớp con của Prototype sẽ gặp khổ cực. Chẳng hạn như việc implement Clone() sẽ khổ cực khi mà những object nội hàm của chúng không suport việc sao chép hoặc có một reference không sao chép được reference.
Xem Thêm  Đính kèm các trình xử lý sự kiện vào các phần tử JavaScript được tạo động - javascript đính kèm trình xử lý sự kiện

Chẳng hạn 1:
Tạo đối tượng nguyên mẫu interface Prototype & một nguyên mẫu ConcretePrototype1 triển khai rõ ràng của nguyên mẫu trên. Class Client sẽ tạo instance ConcretePrototype1 & clone thành 10 bản khác nhau & biến đổi giá trị Ҳ.

#Client.java

package prototypePattern.demo1;

public class Client {
	public static void main(String[] args) throws CloneNotSupportedException {
		ConcretePrototype1 ᴘ = new ConcretePrototype1(1000);

		for (int ι = 0; ι < 10; ι++) {
			Prototype pclone = ᴘ.clone();
			pclone.setX(ᴘ.getX()*ι);
			pclone.printX();
		}
	}
}

#Prototype.java

package prototypePattern.demo1;

public interface Prototype {
	public void setX(int Ҳ);

	public int getX();

	public void printX();
}

#ConcretePrototype1.java

package prototypePattern.demo1;

public class ConcretePrototype1 implements Prototype, Cloneable {
	private int Ҳ;
	
	public ConcretePrototype1(int Ҳ) {
		setX(Ҳ);
	}
	
	@Override
	public void setX(int Ҳ) {
		this.Ҳ = Ҳ;
	}

	@Override
	public int getX() {
		return this.Ҳ;
	}

	@Override
	public void printX() {
		System.out.println("Value: " + this.Ҳ);
	}
	
	@Override
	protected ConcretePrototype1 clone() throws CloneNotSupportedException {
		return (ConcretePrototype1)super.clone();
	}
}

Tải source code: tại đây

Chẳng hạn 2:
Tạo nguyên mẫu abstract prototype Employee & có 2 lớp Developer, Typist là 2 nguyên mẫu triển khai rõ ràng concretePrototype. Tất cả chúng ta sẽ clone chúng trong class Client.

#Client.java

package prototypePattern.demo2;

public class Client {
	public static void main(String[] args) throws CloneNotSupportedException{
		Developer dev = new Developer();
		dev.setName("Nguyen Ngoc Anh");
		dev.setRole("Software Enginer");
		dev.setPreferredLanguage("Java");
		
		Developer devCopy = (Developer)dev.clone();
		devCopy.setName("Nguyen Hai Phong");
		devCopy.setPreferredLanguage("PHP");
		
		dev.getDetail();
		devCopy.getDetail();
		
		/** OUTPUT
		 * Name: Nguyen Ngoc Anh - Role: Phần mềm Enginer - PreferredLanguage: Java
		 * Name: Nguyen Hai Phong - Role: Phần mềm Enginer - PreferredLanguage: PHP
		 */
		
		Typist typ = new Typist();
		typ.setName("Nguyen Thao My");
		typ.setRole("Typist");
		typ.setWordsPerMinute(250);
		
		Typist typCopy = (Typist)typ.clone();
		typCopy.setName("Ha Ngoc Bao");
		typCopy.setWordsPerMinute(300);
		
		typ.getDetail();
		typCopy.getDetail();
		
		/** OUTPUT
		 * Name: Nguyen Thao My - Role: Typist - WordsPerMinute: 250wpm
		 * Name: Ha Ngoc Bao - Role: Typist - WordsPerMinute: 300wpm
		 */
	}
}

#EmployeeAbstract.java

package prototypePattern.demo2;

public abstract class EmployeeAbstract implements Cloneable {
	private String name;
	private String role;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	
	public void getDetail(){
		System.out.println(this.toString());
	}
	
	@Override
	protected EmployeeAbstract clone() throws CloneNotSupportedException {
		// Shallow Sao chép: only top-level objects are duplicated
		return (EmployeeAbstract)super.clone();
	}
}

#Developer.java

package prototypePattern.demo2;

public class Developer extends EmployeeAbstract {
	private String preferredLanguage;
	
	public String getPreferredLanguage() {
		return preferredLanguage;
	}

	public void setPreferredLanguage(String preferredLanguage) {
		this.preferredLanguage = preferredLanguage;
	}

	@Override
	public String toString() {
		return ("Name: " + this.getName() + " - Role: " + this.getRole() + " - PreferredLanguage: " + this.getPreferredLanguage() + "wpm");
	}		

}

#Typist.java

package prototypePattern.demo2;

public class Typist extends EmployeeAbstract {
	private int wordsPerMinute;
	
	public int getWordsPerMinute() {
		return wordsPerMinute;
	}

	public void setWordsPerMinute(int wordsPerMinute) {
		this.wordsPerMinute = wordsPerMinute;
	}

	@Override
	public String toString() {
		return ("Name: " + this.getName() + " - Role: " + this.getRole() + " - WordsPerMinute: " + this.getWordsPerMinute() + "wpm");
	}
}

Tải source code: tại đây

Xem Thêm  Thêm thuộc tính CSS vào một phần tử bằng JavaScript / jQuery - javascript thêm css vào phần tử

Rate this:

Share this:

Like this:

Like

Loading…

Viết một bình luận