Виділення приватного класу даних

Виділення приватного класу даних (Private class data) - це структурний шаблон проєктування, який використовується для інкапсуляції атрибутів і маніпуляції нам ними. Частковий випадок рефакторингу - "Extract Class".

Стандартна документація

Категорії документації для шаблону проєктування private class data описані згідно з матеріалами книги Gang of Four.

Ім'я та класифікація

Назва шаблону
Цей шаблон проєктування відомий як private class data.
Класифікація шаблону
Це один зі структурних шаблонів проєктування.

Мета

Шаблон проєктування private class data прагне до скорочення стороннього впливу на атрибути, обмежуючи їх область видимості. Він скорочує кількість атрибутів класу інкапсулюючи їх в Data об'єкт. Це дозволяє позбутись прав на зміну атрибутів, які за задумом, мають бути незмінними після того, як вони були ініціалізовані в конструкторі. Атрибути не можуть бути змінені навіть методами цільового класу.

Також відомий як

Pimpl (Private IMPLementation) чи непрозорий вказівник

Мотивація

Клас може змінювати значення атрибутів, навіть якщо такі зміни є небажані. Наприклад: після ініціалізації атрибутів в конструкторі класу. Використання шаблону проєктування private class data запобігає таким небажаним змінам.

Клас може мати одноразово-змінювані які не можуть бути оголошені з ключовим словом final. Використання цього шаблону дозволяє реалізувати одноразове надання значень цим атрибутам.

Ідея створення такого шаблону походить від тези про захист стану об'єкта класу шляхом мінімізації області видимості його атрибутів (даних).

Застосовність

Цей шаблон проєктування є застосовний для будь-якого класу в будь-якій об'єктно-орієнтованій мові програмування.

Наслідки

Наслідки використання цього шаблону проєктування включають в себе наступне:

  • Контроль прав на запис для атрибутів класу;
  • Відділення даних від методів які використовують ці дані;
  • Інкапсуляція ініціалізації атрибутів (даних) класу;
  • Введення нового типу для службового слова final: незмінність після конструктора;

Реалізація

Шаблон проєктування private class data вирішує проблеми описані вище. Наслідками його застосування є:

  • Клас даних доступається до кожного атрибута (змінної чи властивості) через getter.
  • Клас даних змінює кожний атрибут (змінну чи властивість) після виходу з конструктора - лише через setter.

Зразки коду

Код на C#, наведений нижче, ілюструє те, яким чином можна застосувати цей шаблон:

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)
    {
        //...
    }
}

Атрибути radius, color і origin, наведені вище не повинні змінюватись в конструкторі Circle(). Зверніть увагу що їх область видимості обмежена, оскільки вони оголошені як private, але методи класу Circle все ще можуть модифікувати їх. Надмірний вплив атрибутів створює (небажаний) зв'язок між методами які доступаються до атрибутів. Щоб зменшити область видимості атрибутів і, таким чином, зменшити зв'язність коду, ми застосуємо шаблон private class data, як показано нижче:

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 2 * this.circleData.Radius * Math.PI; }
    }
    public double Diameter
    {
        get { return this.circleData.Radius * 2; }
    }
    public void Draw(Graphics graphics)
    {
        //...
    }
}

Клас Circle тепер має атрибут типу CircleData який інкапсулює атрибути, які раніше були доступні напряму з класу Circle. Це застерігає методи класу від зміни атрибутів після того, як був викликаний конструктор класу Circle(). Зауважте, що не зважаючи на це, методи класу Circle все ще можуть повертати значення інкапсульованих атрибутів.

Код на php.

До застосування шаблону:

class Circle 
{
    private $radius;
    private $color;
    private $origin;
    public function __construct($radius, $color, $origin) 
    {
        $this->radius = $radius;
        $this->color = $color;
        $this->origin = $origin;
    }
    public function getCircumference() 
    {
        return 2 * M_PI * $this->radius;
    }
    public function getDiameter() 
    {
        return 2 * $this->radius;
    }
    public function draw() 
    {
	//...    
    }
 }
І після:
class CircleData 
{
    private $radius;
    private $color;
    private $origin;
    public function __construct($radius, $color, $origin) 
    {
        $this->radius = $radius;
        $this->color = $color;
        $this->origin = $origin;
    }
    public function getRadius() 
    {
        return $this->radius;
    }
    public function getColor() 
    {
        return $this->color;
    }
    public function getOrigin() 
    {
        return $this->origin;
    }
}

class Circle 
{
    private $circleData;
    public function __construct($radius, $color, $origin) 
    {
        $this->circleData = new CircleData($radius, $color, $origin);
    }
    public function getCircumference() 
    {
        return $this->circleData->getRadius() * M_PI;
    }
    public function getDiameter() 
    {
        return $this->circleData->getRadius() * 2;
    }
    public function draw() 
    {
	//...
    }
}

Пов'язані шаблони проєктування

Посилання

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.