Một số ưu và nhược điểm
Ưu điểm cho đa hình:
- Một giao diện đa hình nhỏ hơn dễ đọc hơn. Tôi chỉ phải nhớ một phương pháp.
- Nó đi với cách ngôn ngữ được sử dụng - Gõ vịt.
- Nếu nó rõ ràng những đối tượng tôi muốn kéo một con thỏ ra khỏi, dù sao cũng không nên có sự mơ hồ.
- Thực hiện nhiều kiểm tra loại được coi là xấu ngay cả trong các ngôn ngữ tĩnh như Java, trong đó có nhiều kiểm tra loại cho loại đối tượng tạo mã xấu, nên pháp sư thực sự cần phân biệt giữa loại đối tượng mà anh ta kéo thỏ ra khỏi ?
Ưu điểm cho quảng cáo:
- Nó ít rõ ràng hơn, tôi có thể kéo một chuỗi ra khỏi một
Cat
thể hiện không? Điều đó sẽ làm việc? nếu không, hành vi là gì? Nếu tôi không giới hạn loại ở đây, tôi phải làm như vậy trong tài liệu hoặc trong các thử nghiệm có thể làm cho hợp đồng tồi tệ hơn.
- Bạn có tất cả cách xử lý kéo một con thỏ ở một nơi, Pháp sư (một số người có thể coi đây là một kẻ lừa đảo)
- Các trình tối ưu hóa JS hiện đại khác nhau giữa các hàm đơn hình (chỉ hoạt động trên một loại) và các hàm đa hình. Họ biết cách tối ưu hóa những cái đơn hình tốt hơn nhiều nên
pullRabbitOutOfString
phiên bản có thể sẽ nhanh hơn nhiều trong các động cơ như V8. Xem video này để biết thêm thông tin. Chỉnh sửa: Tôi đã tự viết một bản hoàn hảo, hóa ra trong thực tế, điều này không phải lúc nào cũng đúng .
Một số giải pháp thay thế:
Theo tôi, kiểu thiết kế này không phải là 'Java-Scripty' để bắt đầu. JavaScript là một ngôn ngữ khác với các thành ngữ khác nhau từ các ngôn ngữ như C #, Java hoặc Python. Những thành ngữ này bắt nguồn từ nhiều năm các nhà phát triển cố gắng hiểu các phần yếu và mạnh của ngôn ngữ, điều tôi muốn làm là cố gắng gắn bó với các thành ngữ này.
Có hai giải pháp hay mà tôi có thể nghĩ ra:
- Nâng cao các vật thể, làm cho các vật thể "có thể kéo được", làm cho chúng phù hợp với một giao diện trong thời gian chạy, sau đó có phép thuật hoạt động trên các vật thể có thể kéo được.
- Sử dụng mô hình chiến lược, dạy cho Magician một cách linh hoạt cách xử lý các loại đối tượng khác nhau.
Giải pháp 1: Vật nâng
Một giải pháp phổ biến cho vấn đề này là 'nâng cao' các vật thể với khả năng có những con thỏ kéo ra khỏi chúng.
Đó là, có một chức năng lấy một số loại đối tượng và thêm kéo ra khỏi mũ cho nó. Cái gì đó như:
function makePullable(obj){
obj.pullOfHat = function(){
return new Rabbit(obj.toString());
}
}
Tôi có thể tạo các makePullable
hàm như vậy cho các đối tượng khác, tôi có thể tạo một makePullableString
, v.v. Tôi đang xác định chuyển đổi trên từng loại. Tuy nhiên, sau khi tôi nâng các đối tượng của mình, tôi không có loại nào để sử dụng chúng theo cách chung chung. Một giao diện trong JavaScript được xác định bằng cách gõ vịt, nếu nó có pullOfHat
phương thức tôi có thể kéo nó bằng phương thức của Magician.
Sau đó, Magician có thể làm:
Magician.pullRabbit = function(pullable) {
var rabbit = obj.pullOfHat();
return {rabbit:rabbit,text:"Tada, I pulled a rabbit out of "+pullable};
}
Nâng cao các đối tượng, sử dụng một số kiểu mẫu mixin có vẻ như là việc cần làm nhiều hơn. (Lưu ý đây là vấn đề với các loại giá trị trong ngôn ngữ là chuỗi, số, null, không xác định và boolean, nhưng tất cả chúng đều có thể đóng hộp)
Dưới đây là một ví dụ về những mã như vậy có thể trông như thế nào
Giải pháp 2: Mô hình chiến lược
Khi thảo luận về câu hỏi này trong phòng trò chuyện JS trong StackOverflow, bạn tôi phenomnomnominal đã đề nghị sử dụng mẫu Chiến lược .
Điều này sẽ cho phép bạn thêm các khả năng để kéo thỏ ra khỏi các đối tượng khác nhau trong thời gian chạy và sẽ tạo mã rất JavaScript. Một pháp sư có thể học cách kéo các vật thể khác nhau ra khỏi mũ và nó kéo chúng dựa trên kiến thức đó.
Đây là cách nó có thể trông trong CoffeeScript:
class Magician
constructor: ()-> # A new Magician can't pull anything
@pullFunctions = {}
pullRabbit: (obj) -> # Pull a rabbit, handler based on type
func = pullFunctions[obj.constructor.name]
if func? then func(obj) else "Don't know how to pull that out of my hat!"
learnToPull: (obj, handler) -> # Learns to pull a rabbit out of a type
pullFunctions[obj.constructor.name] = handler
Bạn có thể xem mã JS tương đương ở đây .
Bằng cách này, bạn được hưởng lợi từ cả hai thế giới, hành động làm thế nào để kéo không được kết hợp chặt chẽ với các đối tượng hoặc Pháp sư và tôi nghĩ rằng điều này tạo ra một giải pháp rất hay.
Cách sử dụng sẽ là một cái gì đó như:
var m = new Magician();//create a new Magician
//Teach the Magician
m.learnToPull("",function(){
return "Pulled a rabbit out of a string";
});
m.learnToPull({},function(){
return "Pulled a rabbit out of a Object";
});
m.pullRabbit(" Str");