SOLID principles in php

SOLID: Първите 5 принципа на обектно ориентиран софтуерен дизайн, част: 2 Принцип отворено-затворен

Част 1 – SOLID: Първите 5 принципа на обектно ориентиран софтуерен дизайн, част: 1 Принцип на единна отговорност

Част 2 – SOLID: Първите 5 принципа на обектно ориентиран софтуерен дизайн, част: 2 Принцип отворено-затворен

Част 3 – SOLID: Първите 5 принципа на обектно ориентиран софтуерен дизайн, част: 3 Принцип на заместване на Лисков

Част 4 – SOLID: Първите 5 принципа на обектно ориентиран софтуерен дизайн, част: 4 Принцип за разделяне на интерфейсите – ISP

Част 5 – SOLID: Първите 5 принципа на обектно ориентиран софтуерен дизайн, част: 5 Принцип на обръщане на зависимостите – DIP

Отворено-затвореният принцип (OCP) гласи:

Обектите трябва да са отворени за разширение, но затворени за модификация за други програмисти.

Това означава, че един клас трябва да бъде разширяем, без да се модифицира самият клас .

Нека да разгледаме отново AreaCalculator класа и да се съсредоточим върху sum метода:

class AreaCalculator
{
    protected $shapes;

    public function __construct($shapes = [])
    {
        $this->shapes = $shapes;
    }

    public function sum()
    {
        foreach ($this->shapes as $shape) {
            if (is_a($shape, 'Square')) {
                $area[] = pow($shape->length, 2);
            } elseif (is_a($shape, 'Circle')) {
                $area[] = pi() * pow($shape->radius, 2);
            }
        }

        return array_sum($area);
    }
}

Помислете за сценарий, при който потребителят би искал метода sum да има допълнителни форми като триъгълници, петоъгълници, шестоъгълници и т.н. Ще трябва постоянно да редактирате този файл и да добавяте още if/ else блокове. Това би нарушило принципа отворено-затворено.

Начинът, по който можете да направите този sum метод по-добър, е да премахнете логиката за изчисляване на площта на всяка форма от AreaCalculator метода на класа и да я прикрепите към класа на всяка форма.

Ето area метода, дефиниран в Square:

class Square
{
    public $length;

    public function __construct($length)
    {
        $this->length = $length;
    }

    public function area()
    {
        return pow($this->length, 2);
    }
}

И ето area метода, дефиниран в Circle:

class Circle
{
    public $radius;

    public function construct($radius)
    {
        $this->radius = $radius;
    }

    public function area()
    {
        return pi() * pow($shape->radius, 2);
    }
}

След това sum методът за AreaCalculator може да бъде пренаписан като:

class AreaCalculator
{
    // ...

    public function sum()
    {
        foreach ($this->shapes as $shape) {
            $area[] = $shape->area();
        }

        return array_sum($area);
    }
}

Сега можете да създадете друг клас на форма и да го предадете, когато изчислявате сумата, без да нарушавате кода.

Възниква обаче друг проблем. Как да разберете, че обектът, прехвърлен в, AreaCalculator всъщност е форма или ако формата има метод с име area?

Кодирането на интерфейс е неразделна част от SOLID.

Създайте файл, ShapeInterfaceкойто поддържа area:

interface ShapeInterface
{
    public function area();
}

Промяна на формата ви класове implement на ShapeInterface.

Ето актуализацията за Square:

class Square implements ShapeInterface
{
    // ...
}

А ето и актуализацията за Circle:

class Circle implements ShapeInterface
{
    // ...
}

В sum метода за AreaCalculator, можете да проверите дали предоставените форми същност са екземпляри на ShapeInterface; в противен случай покажете изключение( throw ):

class AreaCalculator
{
    // ...

    public function sum()
    {
        foreach ($this->shapes as $shape) {
            if (is_a($shape, 'ShapeInterface')) {
                $area[] = $shape->area();
                continue;
            }

            throw new AreaCalculatorInvalidShapeException();
        }

        return array_sum($area);
    }
}

Това отговаря на принципа отворено-затворено в SOLID

Вашият коментар