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

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Виділення приватного класу даних (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 [Архівовано 17 березня 2015 у Wayback Machine.].
  • Клас даних змінює кожний атрибут (змінну чи властивість) після виходу з конструктора - лише через setter [Архівовано 17 березня 2015 у Wayback Machine.].

Зразки коду[ред. | ред. код]

Код на 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() 
    {
	//...
    }
}

Застосування[ред. | ред. код]

Пов'язані шаблони проєктування[ред. | ред. код]

Посилання[ред. | ред. код]