Webmaster общности: Predpriemach.com | SearchEngines.bg

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

    php-solid-principles

    Част 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