2009-06-19 45 views
6

Tôi là người mới bắt đầu trong Mẫu thiết kế.Mẫu thiết kế - Mẫu chiến lược

Giả sử tôi đang phát triển ứng dụng C# để theo dõi các công trình phát triển được thực hiện bởi các thành viên khác nhau trong nhóm phát triển (tức là Trình theo dõi dự án).

Tôi đang cố gắng lấy cảm hứng từ Mô hình chiến lược.

Vì vậy, tôi đang thiết kế các lớp và các giao diện của tôi như sau:

interface IEmployee 
{ 
    void Retires(); 
    void TakesLeave(); 
} 

interface IResponsible 
{ 
void AcknowledgeJobAccomplish(); 
void CompletesJob(); 
} 

interface ILeader 
{ 
    void FormsTeam(); 
    void RecruitsNewMember(); 
    void KicksOutMemberFromTheTeam(); 
    void AssignsJob(); 
void UnassignsJob(); 
void QueriesTheJobStatus(); 
void ChangesTheJobStatus(); 
} 

interface IPersistent 
{ 
    void Save(); 
    void Update(); 
    void Delete(); 
} 

abstract class TeamMember : IEmployee, IResponsible, IPersistent 
{ 
    string Name; 
} 

class Programmer : TeamMember 
{ 
} 

class LeadProgrammer : Programmer, ILeader 
{ 
    ProgrammerCollection associateProgrammers; 
} 

class ProjectManager : TeamMember, ILeader 
{ 
    TeamMemberCollection teamMembers; 
} 

abstract class Tester : TeamMember 
{ 
} 

class UnitTester : Tester 
{ 
} 

class QC : Tester 
{ 
} 

class SupportStaff : TeamMember 
{ 
} 

Tôi nên làm gì để cải thiện điều thiết kế này?

+0

TeamMamber: TeamMember (đánh vần lỗi tôi nghĩ) –

Trả lời

8

Vâng, trước hết, những gì bạn có ở đó không phải là một ví dụ về mẫu Chiến lược. Strategy Pattern cho phép đặc tả động của một phương pháp để hoàn thành công việc. Những gì bạn có ở đây thực sự là một thiết kế giao diện chuẩn, nơi bạn phân bổ trách nhiệm và khả năng bằng cách thừa kế giao diện.

Chỉnh sửa: Hãy sử dụng ví dụ. Giả sử bạn có một nhóm Công nhân; bạn cũng có một bộ Công việc. Mỗi công nhân có thể thực hiện một nhiệm vụ. Các nhiệm vụ này có thể bao gồm một số thứ như DoFoo() và DoBar(). Mỗi công nhân không biết họ sẽ thực hiện nhiệm vụ nào; họ chỉ biết khi nào họ xuất hiện rằng họ sẽ làm một nhiệm vụ.

Vì vậy, chúng tôi sẽ muốn mô hình Công nhân là có một Tác vụ mà họ sẽ thực hiện. Vì các Tác vụ khác nhau rất nhiều, chúng tôi sẽ triển khai Tác vụ dưới dạng giao diện.

Vì vậy, chúng tôi sẽ có:

public class Worker 
{ 
    public Task myTask; 

    public Worker(Task task) 
    { 
     myTask = task; 
    } 

    public void DoWork() 
     { 
     myTask.DoTask(); 
     } 
    } 
} 

Interface Task 
{ 
    void DoTask(); 
} 

public class Task1 : Task 
{ 
    public void DoTask() 
    { 
    // Do whatever Task1 will do 
    } 
} 

public class Task2 : Task 
{ 
    public void DoTask() 
    { 
    // Do whatever Task2 will do 
    } 
} 

public class Job 
{ 
    public List<Worker> workers; 

    public void Job() 
    { 
     workers.Add(new Worker(new Task1())); 
     workers.Add(new Worker(new Task2())); 
    } 

    public void DoJob() 
    { 
     foreach (Worker worker in workers) 
     { 
     worker.DoWork(); 
     } 
    } 

    public void ChangeJobsToTask1() 
    { 
     foreach (Worker worker in workers) 
     { 
     worker.myTask = new Task1(); 
     } 
    } 

    public void ChangeJobsToTask2() 
    { 
     foreach (Worker worker in workers) 
     { 
     worker.myTask = new Task2(); 
     } 
    } 
} 

Vì vậy, những gì xảy ra là khi chúng ta khởi tạo một Job, các Job tạo ra hai Worker s. Worker đầu tiên có tác vụ Task1; số Worker thứ hai có tác vụ Task2. Để thực hiện các Worker s làm họ Task s, chúng ta gọi là phương pháp DoJob() trên lớp Job, mà chỉ gọi phương thức DoWork() trên mỗi Worker s, do đó gọi phương thức DoTask() trên mỗi Task s rằng Worker s được thiết lập với.

Nếu chúng ta muốn thay đổi Worker s cho tất cả làm Task1, chúng ta gọi là phương pháp ChangeJobsToTask1(), thiết lập Task để Task1 cho tất cả các đối tượng Worker chứa bởi Job; nếu, tại thời điểm đó, chúng tôi gọi là DoJob() trên đối tượng Job, tất cả các Worker sẽ thực hiện tác vụ Task1. Tương tự, nếu chúng tôi muốn thay đổi Task s thành Task2, chỉ cần gọi phương thức ChangeJobsToTask2(); tất cả các Worker s sau đó sẽ thực hiện Task2.DoTask() khi phương thức DoWork() của chúng được gọi.

Điểm quan trọng của sự trừu tượng ở đây là Worker s hiển thị phương pháp DoWork(), nhưng chúng không nhất thiết phải biết công việc đang được thực hiện. Tức là, Task s cho các số Worker s có thể hoán đổi cho nhau; các Worker s chỉ biết rằng họ sẽ làm một Task, nhưng các chi tiết cụ thể của những gì nó là không quan trọng đối với các Worker s.

+0

Từ cuốn sách Head First Design Patterns, tôi thấy các nguyên tắc "Xác định các khía cạnh của ứng dụng của bạn mà thay đổi và tách chúng ra khỏi những gì tương tự vẫn". Bạn có thể đề xuất cho tôi cách tôi nên thực hiện việc này không? –

+1

@ JMSA: Tôi không thể đề xuất cách thực hiện điều đó mà không biết tất cả về ứng dụng của bạn, nhưng tôi sẽ thêm thông tin vào câu trả lời để minh họa ví dụ. –

+0

Từ tất cả các cuộc thảo luận này, tôi thực sự thấy rằng, ví dụ của tôi không hoàn hảo cho Mô hình Chiến lược được triển khai. Phải không? –

2

Tôi không thấy mẫu chiến lược trong ví dụ của bạn. Mô hình chiến lược lấy lớp "chiến lược" (thường kế thừa từ một Giao diện với một phương thức logic, ví dụ "DoJob()") trong tham số và khi một phương thức được gọi, nó sẽ hoạt động bằng cách áp dụng chiến lược đi trước mà không biết nó là gì sẽ cụ thể làm.

Trong ví dụ của bạn, bạn có thể có một lớp mà tất cả mọi người của bạn kế thừa có một SetJob (IJobStrategy) và có một phương thức DoJob() sẽ gọi giao diện DoJob() (từ IJobStrategy). Hơn nữa, bạn có thể có nhiều công việc cụ thể kế thừa IJobStrategy. Bằng cách này, người của bạn không biết công việc và bạn có thể thay đổi công việc mà không phải sửa đổi lớp người đó.

Bạn có thể xem ví dụ và thông tin thêm here.

0

Điều này có vẻ giống với Nguyên tắc phân đoạn giao diện. Bây giờ, điều đó chơi tốt với chiến lược, nhưng đây là những gì tôi muốn làm khác nhau.

Trình kiểm tra sẽ không phải là lớp Bê tông, nó sẽ là một TeamMember với một TesterCompletesJobStrategy được cấu hình vì nó là CompletesJobStrategy. Xét cho cùng, điều duy nhất giữ tôi khỏi thử nghiệm là nhiệm vụ hiện tại của tôi trong nhóm.

Cũng giống như một điểm thảo luận, tôi sẽ bắt đầu với một cái gì đó giống như thế này nếu tôi đang nhắm mục tiêu Chiến lược.

interface ICompleteJobStrategy { 
    void CompleteJob(IResponsible responsibleParty); 
} 
class TesterCompletJobStrategy : ICompleteJobStrategy { 
    ... 
} 
class TeamMember : IResponsible { 
    TeamMember(ICompleteJobStrategy strat){ .. }; 
    void CompleteJob() { _completeJobStrategy.CompleteJob(this) ; } 
} 
+0

Bạn không cần 'công khai' trong giao diện –

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