2015-04-26 11 views
5

Tôi đang tham gia một lớp mẫu thiết kế ở trường, và đã đọc qua một số chương của Head First Design Patterns. Những gì tôi muốn tìm hiểu là ở mức độ nào mà các mẫu thiết kế có thể ngăn chặn việc viết lại mã hiện có.Bạn có thể ngăn chặn việc sửa đổi mã hiện tại khi sử dụng các mẫu thiết kế ở mức độ nào?

Hãy để chúng tôi chụp Duck lớp học và FlyBehavior các lớp học chẳng hạn. Tôi có trong public static void main(String[] args) đoạn mã sau:

Duck mallard = new MallardDuck(new FlyWithWings()); 

Am Tôi đúng khi nói rằng nó là không thể tránh khỏi rằng bạn sẽ phải thay đổi phương pháp main() của bạn khi bạn muốn thêm một chiến lược mới? Bằng cách đó, bạn sửa đổi mã hiện tại, phải không? Tôi đặc biệt đề cập đến một phần, nơi một lớp chiến lược cụ thể được đề cập: new FlyWithWings().

Nếu bạn thực hiện phương pháp mô hình nhà máy trong mã của bạn, bạn có thể ngăn chặn việc có một lớp bê tông (FlyWithWings) khỏi bị nêu tại tất cả:

public FlyBehavior returnBehavior(FlyBehaviorFactory factory, String behaviorType) { 
    return factory.getFlyBehavior(behaviorType); 
} 

Và do đó, có dòng mã sau đây:

Duck mallard = new MallardDuck(returnBehavior(flyFactory, "wings")); 

Bằng cách này, một phần nào đó của chương trình của bạn không nhất thiết phải biết về những gì FlyBehaviorFactory để sử dụng. Tuy nhiên, phương thức main() của bạn sẽ vẫn phải chỉ định một số tham số nhất định trong phương thức returnBehavior để biết nhà máy sẽ tạo chiến lược gì. Vì vậy, tôi có quyền nói rằng bạn vẫn sẽ phải sửa đổi main() nếu tôi đã thêm một lớp FlyBehavior mới và muốn thêm thông số đó làm tham số cho returnBehavior()?

Có thể cải thiện tình huống này thêm nữa không?

+0

Bạn nên xem [_dependency injection_] (http://en.wikipedia.org/wiki/Dependency_injection) và các khung công tác khác nhau cho nó. – Seelenvirtuose

+0

@Synchro Vui lòng đọc: [Tôi nên làm gì khi ai đó trả lời câu hỏi của tôi] (http://stackoverflow.com/help/someone-answers) – CKing

Trả lời

0

Trong ví dụ hiện tại, bạn đang mã hóa cứng các thông số được chuyển đến nhà máy của bạn và do đó quyết định hành vi tại compile time.

Duck mallard = new MallardDuck(returnBehavior(flyFactory, "wings")); 

Điều này có thể được thay đổi để cắm một hành vi đặc biệt tại runtime thay vì compile time:

Duck mallard = new MallardDuck(returnBehavior(flyFactory, args[0])); 

Với sự thay đổi trên, bạn sẽ không bao giờ phải thay đổi phương thức main của bạn. nhà máy của bạn có thể được viết theo một cách mà nó throws một exception khi một hành vi nhận được trong thời gian chạy là không có sẵn:

if(behaviorType.equals("wings") { 
    //...create FlyWithWings 
} else{ 
    //throw an appropriate exception indicating that the behavior does not exist 
} 

Điều đó đang được nói, nó là không thể tránh khỏi phải thay đổi mã nếu một hành vi mới được giới thiệu. Mặc dù, thay đổi này sẽ ở một nơi duy nhất và ở phía sau ứng dụng của bạn nhiều nhất có thể, tức là số factory của bạn, đó là toàn bộ thời điểm factory ngay từ đầu. Ngoài ra, khi bạn tạo một FlyBehavior mới, bạn đang làm như vậy bằng cách mở rộng từ một lớp hiện có. Điều này là nội tuyến với open-closed principle

0

Những gì bạn đang làm ở đây là tiêm phụ thuộc, bạn đang tiêm FlyBehaviour vào Vịt. Đôi khi khi sử dụng tiêm phụ thuộc như thế này bạn có thể có một chuỗi tiêm. Ví dụ nếu bạn muốn một chiến lược tốc độ được tiêm vào FlyBehaviour bạn có thể có một cái gì đó như thế này.

Duck mallard = new MallardDuck(new FlyWithWings(new FastSpeed())); 

Sẽ không tốt nếu bạn có bất kỳ lớp nào trong số này và phải thay đổi mọi lúc. Một giải pháp tốt hơn là sử dụng một thùng chứa phụ thuộc tiêm chịu trách nhiệm tạo ra mỗi lớp này. Sau đó, trong chính bạn chỉ có thể gọi một cái gì đó như thế này

Duck mallard = (Duck) Container.get('Duck'); 

Thùng chứa có trách nhiệm tạo tất cả các trường hợp cần thiết để tiêm. Vì vậy, để trả lời câu hỏi của bạn, bạn sẽ cần phải thay đổi mã của bạn khi muốn một chiến lược mới nhưng ít nhất theo cách này nó chỉ ở một nơi thay vì trong suốt mã của bạn mà có thể là nhiều tập tin.

Các vấn đề liên quan