Tôi đang theo dõi câu hỏi này , nhưng tôi đang chuyển trọng tâm của mình từ mã sang nguyên tắc.
Từ sự hiểu biết của tôi về nguyên tắc thay thế Liskov (LSP), bất kể phương pháp này trong lớp cơ sở của tôi, họ phải được thực hiện trong lớp con của tôi, và theo này trang, nếu bạn ghi đè một phương pháp trong các lớp cơ sở và nó không làm gì hoặc ném một ngoại lệ, bạn đang vi phạm nguyên tắc.
Bây giờ, vấn đề của tôi có thể được tóm tắt như thế này: tôi có một bản tóm tắt Weapon
class
, và hai lớp, Sword
và Reloadable
. Nếu Reloadable
chứa một cụ thể method
, được gọi Reload()
, tôi sẽ phải downcast để truy cập vào đó method
, và, lý tưởng nhất, bạn muốn tránh điều đó.
Sau đó tôi nghĩ đến việc sử dụng Strategy Pattern
. Bằng cách này, mỗi vũ khí chỉ nhận thức được các hành động mà nó có khả năng thực hiện, vì vậy, ví dụ, Reloadable
vũ khí, rõ ràng có thể tải lại, nhưng Sword
không thể, và thậm chí không nhận ra Reload class/method
. Như tôi đã nói trong bài viết Stack Overflow của mình, tôi không phải xem thường và tôi có thể duy trì một List<Weapon>
bộ sưu tập.
Trên một diễn đàn khác , câu trả lời đầu tiên đề nghị cho phép Sword
nhận thức được Reload
, chỉ cần đừng làm gì cả. Câu trả lời tương tự này được đưa ra trên trang Stack Overflow mà tôi đã liên kết ở trên.
Tôi không hiểu tại sao. Tại sao vi phạm nguyên tắc và cho phép Sword nhận thức Reload
và để trống? Như tôi đã nói trong bài viết Stack Overflow của tôi, SP, đã giải quyết khá nhiều vấn đề của tôi.
Tại sao nó không phải là một giải pháp khả thi?
public final Weapon{
private final String name;
private final int damage;
private final List<AttackStrategy> validactions;
private final List<Actions> standardActions;
private Weapon(String name, int damage, List<AttackStrategy> standardActions, List<Actions> attacks)
{
this.name = name;
this.damage = damage;
standardActions = new ArrayList<Actions>(standardActions);
validAttacks = new ArrayList<AttackStrategy>(validActions);
}
public void standardAction(String action){} // -- Can call reload or aim here.
public int attack(String action){} // - Call any actions that are attacks.
public static Weapon Sword(String name, damage, List<AttackStrategy> standardActions, List<Actions> attacks){
return new Weapon(name, damage,standardActions, attacks) ;
}
}
Giao diện tấn công và thực hiện:
public interface AttackStrategy{
void attack(Enemy enemy);
}
public class Shoot implements AttackStrategy {
public void attack(Enemy enemy){
//code to shoot
}
}
public class Strike implements AttackStrategy {
public void attack(Enemy enemy){
//code to strike
}
}
reload()
trống hoặc standardActions
không chứa hành động tải lại chỉ là một cơ chế khác. Không có sự khác biệt cơ bản. Bạn có thể làm cả hai. => Giải pháp của bạn là khả thi (đó là câu hỏi của bạn) .; Kiếm không cần biết về tải lại nếu Weapon chứa triển khai mặc định trống.
class Weapon { bool supportsReload(); void reload(); }
. Khách hàng sẽ kiểm tra nếu được hỗ trợ trước khi tải lại.reload
được xác định theo hợp đồng để ném iff!supportsReload()
. Điều đó tuân thủ các lớp học LSP iff tuân thủ giao thức tôi vừa phác thảo.