2011-06-27 24 views
5

我正在查看由Martin Fowler完成的稱爲Dealing With Roles的論文。其中,Fowler針對組織(即員工,工程師,經理,銷售員)中的人員處理角色的三種基本策略包括角色子類型,角色對象和角色關係。角色對象模式問題

在1997年寫作它肯定是舊的,作爲一個「工作草案」它也有一些錯誤,否則將不存在。我很困惑地回顧一下他所經歷的角色對象的例子,並且在下面包含了我的一些c#代碼的c#解釋。

我有三個問題:
(1)有很多字符串的類型識別,似乎它應該可以用泛型替換,但我還無法處理如何這樣做。你將如何使用泛型實現此代碼?
(2)JobRole作爲類型的字符串名稱存在於代碼中,但未與其餘代碼明確定義。我不知道這是否是PersonRole的基類。 JobRole的定義是什麼?單元測試看起來是模式使用的正確例子嗎?
(3)有沒有人有任何關於使用角色對象的更新實現和示例的鏈接?

乾杯,
Berryl

public class PersonWithRoles : Person 
{ 
    private readonly IList<PersonRole> _roles = new List<PersonRole>(); 

    public static PersonWithRoles CreatePersonWithRoles(string identifierName) { 
     ... 
    } 

    public void AddRole(PersonRole role) { _roles.Add(role); } 

    public PersonRole RoleOf(string typeName) { return _roles.FirstOrDefault(x => x.HasType(typeName)); } 
} 

public class PersonRole 
{ 
    public virtual bool HasType(string typeName) { return false; } 
} 

public class Salesman : PersonRole 
{ 
    public override bool HasType(string typeName) 
    { 
     if (typeName.Equals("Salesman", StringComparison.InvariantCultureIgnoreCase)) return true; 
     if (typeName.Equals("JobRole", StringComparison.InvariantCultureIgnoreCase)) return true; 

     return base.HasType(typeName); 
    } 

    public int NumberOfSales { get; set; } 

} 

[TestFixture] 
public class RoleUsageTests 
{ 
    [Test] 
    public void Test() { 
     var p = PersonWithRoles.CreatePersonWithRoles("Ted"); 
     var s = new Salesman(); 
     p.AddRole(s); 

     var tedSales = (Salesman) p.RoleOf("Salesman"); 
     tedSales.NumberOfSales = 50; 
    } 
} 

回答

5

我的信念下,這些類型的應用是很好的候選人使用裝飾設計模式,其中有一個人的基類,然後每個角色都擴展該基類。基類沒有權限聲明 - 只有擴展人員的角色類應該。

對不起,是模糊的,但我希望你得到我想描述的。

class programmer { 
name ... 
email ... 
seat location ... 
} 

class html_coder extends programmer { 
canCodeHTML ... 
} 

class script_coder extends programmer { 
canCodeHTML ... 
canCodeJavascript ... 
} 

class senior_developer extends programmer { 
canCodeHTML ... 
canCodeJavascript ... 
canAccessDatabase ... 
canEditProjectArchitectureFiles ... 
canWearTennisShoesToWork... 
} 

這些都可以擴展程序員基類...注意到程序員類未聲明的權利...只是性能

+0

I * *想這樣。你能否抓取一些示例代碼或者給我一個顯示它的鏈接? Cheer – Berryl

+0

來自Fowler的同一篇論文:「這種模式的一個有用的變化是使角色對象裝飾器成爲核心對象。這意味着只使用員工人員特徵的客戶可以處理單個對象而不處理需要了解角色對象的使用情況,其代價是當人員的界面變化時,所有角色都需要更新。參見[Bäumer等人]瞭解如何做到這一點的更多細節。「 – Berryl

+1

這是Fowler提到的[堡盟工作鏈接](http://hillside.net/plop/plop97/Proceedings/riehle.pdf)。一個由(3)主要參與者組成的模式;使用你的例子,將有一個抽象的程序員,它定義了程序員的接口以及管理角色的接口,然後是一個ProgrammerCore,它實現了Programmer接口和角色補救。最後是一個ProgrammerRole,它裝飾了一個ProgrammerCore的實例.HtmlCoderRole和SeniorDevRole是ProgrammerRole的子類。 – Berryl

1

1)泛型在C#中可以幫助一個整潔的實施
2) JobRole是PersonRole的子類型,是特定作業的超類型

我仍然希望看到使用示例,因爲Fowler對此模式的觀點之一是鍵入靈活性的代價是犧牲的兩步使用模式。使用Decorator模式實現這一點不會改變這一點。例如,要與推銷員角色中的人員一起工作,首先需要獲取某個人的實例,然後查找推銷員的角色。

乾杯,
Berryl

public class Person 
{ 
    public FullName FullName { get; set; } 

    public Person(FullName fullName) { FullName = fullName; } 

    public IList<IRole> Roles { get; private set; } 

    public IRole GetRoleOf<T>() where T: IRole{return Roles.FirstOrDefault(x => x.HasType(typeof(T))); } 

    public void AddRole(IRole role) { Roles.Add(role); } 

    public bool RemoveRole(IRole role) { return Roles.Remove(role); } 

}

public interface IRole 
{ 
    bool HasType(Type type); 
} 

public abstract class Role : IRole 
{ 
    public virtual bool HasType(Type type) { return false; } 
} 

/// <summary> 
/// Base type for any type of role for a person. 
/// </summary> 
public class PersonRole : Role 
{ 
    public override bool HasType(Type type) { return type.Equals(typeof(PersonRole)); } 
} 

/// <summary> 
/// Base type for any type of role for a person. 
/// </summary> 
public class JobRole : Role 
{ 
    public override bool HasType(Type type) { 
     if(type.Equals(GetType())) return true; 
     return base.HasType(type); 
    } 
} 

/// <summary> 
/// Behavior specific to a salesman 
/// </summary> 
public class Salesman : JobRole, ISalesman 
{ 
    public override bool HasType(Type type) 
    { 
     if (type.Equals(GetType())) return true; 
     return base.HasType(type); 
    } 

    public int NumberOfSales { get; set; } 
} 

[TestFixture] 
public class JobRoleTests : BaseTestFixture 
{ 
    private PersonEx _person; 

    protected override void OnFixtureSetUp() { 
     _person = new PersonEx(new OneNameFullName("schmuck")); 
     // can be a Salesman 
     _person.AddRole(new Salesman()); 
    } 

    [Test] 
    public void Salesman_CanGet() { 
     var salesman = _person.GetRoleOf<Salesman>() as Salesman; 
     Assert.That(salesman, Is.Not.Null); 
     salesman.NumberOfSales = 50; 
     Assert.That(salesman.NumberOfSales, Is.EqualTo(50)); 
    } 
}