Bạn đang thực sự sử dụng mẫu khuôn mẫu. Có hai điều chính bạn có thể làm để "ẩn" chi tiết từ người dùng bên ngoài:
1) Hiểu bạn access modifiers:
Access Levels
Modifier | Class | Package | Subclass | World |
--------------------------------------------------
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
no modifier | Y | Y | N | N |
private | Y | N | N | N |
ngắn của tin tặc quyết tâm bắt nạt con đường của họ trong quá khứ những biện pháp bảo vệ với sự phản ánh, những thể giữ các lập trình viên bình thường từ các phương thức gọi vô tình được giữ kín nhất. Các lập trình viên sẽ đánh giá cao điều này. Không ai muốn sử dụng API lộn xộn.
Hiện tại b.doWork()
là protected
. Vì vậy, nó sẽ chỉ hiển thị trong main()
nếu main()
của bạn nằm trong lớp A
(không phải), phân lớp B
(không phải) hoặc trong cùng một gói (không rõ ràng, bạn không đăng bất kỳ manh mối nào về gói) mã của bạn nằm trong).
Điều này đặt ra câu hỏi, bạn đang cố gắng bảo vệ ai khi nhìn thấy b.doWork()
? Nếu gói bạn đang tạo là thứ duy nhất bạn đang phát triển nó có thể không quá tệ. Nếu nhiều người đang dậm dẫm xung quanh trong gói này rối tung với nhiều lớp khác thì không có khả năng họ sẽ quen thuộc với các lớp học A
và B
. Đây là trường hợp bạn không muốn tất cả mọi thứ treo ra nơi mọi người có thể nhìn thấy nó. Ở đây nó sẽ được tốt đẹp để chỉ cho phép truy cập lớp và phân lớp. Nhưng không có công cụ sửa đổi nào cho phép truy cập lớp con mà không cho phép truy cập gói. Miễn là bạn đang phân lớp protected
là cách tốt nhất bạn có thể làm. Với ý nghĩ đó, đừng đi tạo các gói với số lượng lớn các lớp. Giữ các gói chặt chẽ và tập trung. Bằng cách đó hầu hết mọi người sẽ làm việc bên ngoài gói, nơi mọi thứ trông đẹp và đơn giản.
Tóm lại, nếu bạn muốn xem main()
ngăn không cho gọi b.doWork()
đặt main()
vào gói khác.
package some.other.package
public final class Main {
...
}
2) Giá trị của lời khuyên tiếp theo này sẽ khó hiểu với mã hiện tại của bạn vì nó giải quyết các vấn đề sẽ chỉ xuất hiện nếu mã của bạn được mở rộng. Nhưng nó thực sự là quan hệ chặt chẽ với ý tưởng bảo vệ mọi người từ những điều nhìn thấy như b.doWork()
What does "program to interfaces, not implementations" mean?
Trong mã của bạn điều này có nghĩa là nó sẽ tốt hơn nếu chính trông như thế này:
public static void main(String[] args) {
A someALikeThingy = new B(); // <-- note use of type A
someALikeThingy.work(); //The name is silly but shows we've forgotten about B
//and know it isn't really just an A :)
}
Tại sao? Điều gì đang sử dụng loại A
và loại B
vấn đề? Vâng A
gần với giao diện . Lưu ý, ở đây tôi không chỉ có nghĩa là những gì bạn nhận được khi bạn sử dụng từ khóa interface
.Tôi có nghĩa là loại B
là một thực hiện cụ thể của loại A
và nếu tôi không hoàn toàn phải viết mã chống lại B
Tôi thực sự không muốn vì ai biết những gì lạ không A
điều B
có. Điều này là khó hiểu ở đây vì mã trong chính ngắn & ngọt ngào. Ngoài ra, giao diện công khai của A
và B
không phải tất cả khác nhau. Cả hai đều chỉ có một phương thức công khai work()
. Hãy tưởng tượng rằng main()
dài và phức tạp, Hãy tưởng tượng B
có tất cả các phương thức không phải là A
treo nó. Bây giờ hãy tưởng tượng bạn cần tạo ra một lớp C
mà bạn muốn chính xử lý. Nó sẽ không được an ủi để thấy rằng trong khi chính được cho ăn một B
rằng như xa như mọi dòng trong chính biết rằng B
chỉ là một số đơn giản A
như điều. Ngoại trừ một phần sau new
điều này có thể đúng và giúp bạn không làm bất cứ điều gì để main()
nhưng cập nhật rằng new
. Thật vậy, đây không phải là lý do tại sao sử dụng một ngôn ngữ gõ mạnh mẽ đôi khi có thể được tốt đẹp?
<rant>
Nếu bạn nghĩ rằng thậm chí cập nhật phần đó sau new
với B()
là quá nhiều công việc bạn không cô đơn. Đó là nỗi ám ảnh nhỏ đặc biệt là những gì đã cho chúng tôi dependency injection movement mà sinh ra một loạt các khuôn khổ đã thực sự nhiều hơn về tự động hóa xây dựng đối tượng hơn là một tiêm đơn giản mà bất kỳ nhà xây dựng có thể cho phép bạn làm.
</rant >
Cập nhật:
tôi thấy từ ý kiến của bạn mà bạn không muốn tạo ra các gói chặt nhỏ. Trong trường hợp đó, hãy xem xét việc bỏ qua mẫu mẫu dựa trên kế thừa dựa trên mẫu chiến lược dựa trên thành phần. Bạn vẫn nhận được đa hình. Nó chỉ không xảy ra miễn phí. Ít hơn viết mã và gián tiếp. Nhưng bạn có thể thay đổi trạng thái ngay cả khi chạy.
Điều này có vẻ phản trực giác vì bây giờ doWork()
phải được công khai. Loại bảo vệ gì vậy? Giờ thì bạn có thể ẩn hoàn toàn B
phía sau hoặc ngay cả bên trong AHandler
. Đây là một số lớp mặt tiền thân thiện với con người nắm giữ những gì từng là mã mẫu của bạn nhưng chỉ phơi bày work()
. A
chỉ có thể là interface
do đó AHandler
vẫn không biết nó có số B
. Cách tiếp cận này là phổ biến với đám đông tiêm phụ thuộc nhưng chắc chắn không có sức hấp dẫn phổ quát. Một số làm điều đó một cách mù quáng mỗi lần làm phiền nhiều. Bạn có thể đọc thêm tại đây: Prefer composition over inheritance?
"một là dễ dàng có thể vô tình gọi b.doWork()". Có thật không? Nó được bảo vệ, vì vậy chỉ có một hoặc B trường hợp có thể gọi nó. –
Thật không may, vì nó được bảo vệ, tất cả các lớp từ gói có thể gọi nó. Chia gói là một cách để đi, mặc dù tôi muốn tránh có các gói 1 hoặc 2 lớp. –
Không !! Bạn đang mô tả công cụ sửa đổi truy cập mặc định (ví dụ: không có gì). Được bảo vệ có nghĩa là "chỉ có tôi hoặc các lớp học mở rộng tôi mới có thể sử dụng" –