Patrones de diseño estructurales: Private Class Data

Intención del patrón


  • Controlar el acceso de escritura a los atributos de la clase.
  • Separar los datos de los métodos que los usan.
  • Encapsular la inicialización de datos de la clase.
  • Proporcionar la forma de que una vez asignado el valor de un atributo, no vuelva a modificarse.


Ejemplo de problema

Una clase que exponer sus atributos (variables de clase) para ser manipulados. Cuando dicha manipulación ya no es deseada, por ejemplo, tras la ejecución del constructor. El uso del patrón de diseño Private Class Data previene dicha manipulación no deseada.
Una clase puede tener atributos variables que no pueden ser declarados como final. Usando este patrón de diseño permite la asignación por única vez de este tipo de atributos.
La motivación por este patrón de diseño proviene del objetivo de proteger el estado de la clase reduciendo al mínimo la visibilidad de sus atributos.


Discusión

El patrón de diseño Private Class Data busca reducir la exposición de atributos mediante la limitación de su visibilidad.
Reduce el número de atributos de clase encapsulándolos en un único objeto de datos (Data Object). Esto le permite al diseñador de la clase quitar el permiso de escritura de los atributos que estaban pensados para ser asignados sólo al momento de la construcción, incluso desde métodos de la propia clase.

Estructura

Este patrón resuelve el problema arriba planteado mediante la extracción de una clase de datos (Data Class) para la clase que usa esos datos (Target Class) y proporcionándole a ésta, una instancia de la clase extraída.



Check list

  1. Crear una clase de datos. Mover a dicha clase todos los atributos que se necesita ocultar.
  2. Crear en la clase principal una instancia de la clase de datos.
  3. La clase principal debe inicializar a la clase de datos a través del constructor de ésta última.
  4. Exponer cada atributo (variable o propiedad) de la clase de datos a través de un getter.
  5. Exponer cada atributo que puede ser modificado a través de un setter.


Ejemplo en código C#

Antes
Los atributos radius, color y origin, no deberían cambiar después de haberse ejecutado el constructor de la clase Circle. Nótese que la visibilidad ya es limitada al habérlas hecho privadas, pero los métodos aun pueden modificarlos.
A pesar de marcar los atributos de clase como const (o final o ReadOnly dependiendo del lenguaje de programación) hace que los atributos mencionados no puedan ser modificados, pero ésts deben ser seteados en el constructor, por lo cual, no pueden ser declarados así.

public class Circle 
{
  private double radius;
  private Color color;
  private Point origin;
  
  public Circle(double radius, Color color, Point origin) 
  {
    this.radius = radius;
    this.color = color;
    this.origin = origin;
  }
  
  public double Circumference 
  {
    get { return 2 * Math.PI * this.radius; }
  }
  
  public double Diameter 
  {
    get { return 2 * this.radius; }
  }
  
  public void Draw(Graphics graphics) 
  {
    //...
  }
}

Después
La exposición excesiva de los atributos crea un tipo (indeseable) de acoplamiento entre los métodos que tienen acceso a estos atributos. Para reducir la visibilidad de los atributos y así reducir el acoplamiento, se implementa el patrón de diseño Private Class Data como se muestra a continuación:

public class CircleData 
{
  private double radius;
  private Color color;
  private Point origin;
  
  public CircleData(double radius, Color color, Point origin)
  {
    this.radius = radius;
    this.color = color;
    this.origin = origin;
  }
  
  public double Radius 
  {
    get { return this.radius; }
  }
  
  public Color Color 
  {
    get { return this.color; }
  }
  
  public Point Origin 
  {
    get { return this.origin; }
  }
}

public class Circle 
{
  private CircleData circleData;

  public Circle(double radius, Color color, Point origin) 
  {
    this.circleData = new CircleData(radius, color, origin);
  }
  
  public double Circumference 
  {
    get { return this.circleData.Radius * Math.PI; }
  }
  
  public double Diameter 
  {
    get { return this.circleData.Radius * 2; }
  }
  
  public void Draw(Graphics graphics) 
  {
    //...
  }
}

0 comentarios:

Publicar un comentario

Muchas gracias por leer el post y comentarlo.

 
Copyright 2009 Programación SOLIDa
BloggerTheme by BloggerThemes | Design by 9thsphere