2011-06-27 18 views
5

Estoy viendo un documento hecho por Martin Fowler llamado Dealing With Roles. En él, Fowler desglosa tres estrategias básicas para tratar con roles para una Persona en una organización (es decir, Empleado, Ingeniero, Gerente, Vendedor) que incluyen Subtipo de rol, Objeto de rol y Relaciones de rol.Pregunta de patrón de objeto de rol

Habiendo sido escrito en 1997, es ciertamente viejo, y al ser un "borrador de trabajo" también tiene algunos errores que de otro modo no existirían. Estoy confundido repasando un ejemplo de Role Object que él atraviesa, y he incluido una interpretación de mi C# de algunos de sus códigos java a continuación.

Tengo tres preguntas:
(1) hay un montón de identificación del tipo que se realiza con cadenas que parece que debería ser reemplazable con los genéricos, pero no puedo tener una idea de cómo hacerlo todavía. ¿Cómo implementarías este código usando genéricos?
(2) JobRole está en el código como el nombre de la cadena para un tipo pero no está específicamente definido con el resto del código. No puedo decir si esta es una clase base para PersonRole o no. ¿Cuál es la definición de JobRole? ¿La prueba unitaria parece un ejemplo correcto del uso del patrón?
(3) ¿Alguien tiene algún vínculo hacia una implementación más reciente y un ejemplo de uso de un objeto de función?

Cheers,
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; 
    } 
} 

Respuesta

5

estoy bajo la creencia de que este tipo de aplicaciones son buenos candidatos para el uso del patrón de diseño decorador en el que hay una clase base persona y, a continuación, cada rol extiende esa clase base. La clase base no tiene declaraciones de permisos; solo las clases de roles que extiende la persona deberían.

Disculpa por ser vago, pero espero que entiendas lo que intento describir.

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... 
} 

éstos se extienden todas la clase base programador ... cuenta de que la clase de programador no declarar los derechos ... sólo propiedades

+0

I * * pensar así. ¿Podrías tachar un código de muestra o darme un enlace que lo muestre? Cheers – Berryl

+0

del mismo documento de Fowler: "Una variación útil en este patrón es hacer que los objetos decoradores del objeto central. Esto significa que un cliente que utiliza solo las características de la persona empleado puede tratar con un solo objeto y no Necesitamos saber sobre el uso de los objetos de rol. El costo es que cuando la interfaz de la persona cambia, todos los roles necesitan ser actualizados.Ver [Bäumer et al] para más detalles sobre cómo hacer esto. " – Berryl

+1

Aquí está el [enlace al trabajo de Baumer] (http://hillside.net/plop/plop97/Proceedings/riehle.pdf) al que hace referencia Fowler. un patrón compuesto por (3) participantes principales; usando su ejemplo, habría un programador abstracto que define la interfaz para un programador, así como la interfaz para la gestión de roles. Luego hay un Programmercore que implementa tanto la interfaz del programador como la función de gestión. Finalmente, hay un ProgrammerRole que decora una instancia de ProgrammerCore. HtmlCoderRole y SeniorDevRole son subclases de ProgrammerRole. – Berryl

1

1) genéricos en C# pueden ayudar a hacer una aplicación más ordenado
2) JobRole es un subtipo de PersonRole y un super-tipo para trabajos específicos

Me gustaría ver ejemplos de uso, ya que uno de los puntos de Fowler sobre este patrón es que la flexibilidad de tipeo se consigue a expensas de un patrón de uso de dos pasos. Implementar esto usando un patrón Decorator no cambia esto. Por ejemplo, para trabajar con una Persona en el rol de Vendedor, primero necesita obtener una instancia de una persona y luego encontrar el rol de Vendedor.

Saludos,
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)); 
    } 
} 
Cuestiones relacionadas