SOLID: Open/Closed Principle (Zasada otwarte – zamknięte)

Wprowadzenie

W poniższym artykule przedstawię drugą z zasad SOLID wraz z przykładem jej zastosowania.

OCP – Open/Closed Principle (Zasada otwarte – zamknięte)

"Komponenty oprogramowania powinny być otwarte na rozbudowę, ale zamknięte na modyfikacje.

Zasada OCP mówi nam o tym, że klasy aplikacji powinny być projektowane w taki sposób aby możliwe było dodawanie nowych funkcjonalności, bez konieczności wprowadzania modyfikacji do istniejącego kodu. Modyfikacja jest bardzo niepożądana, ponieważ zmiana w jednym miejscu aplikacji może spowodować awarię w jej całkiem innym miejscu.

Przykład zastosowania

Polimorfizm

Polimorfizm jest najczęściej używanym mechanizmem, pozwalającym nam pisać kod zgodnie z zasadą OCP.
Spójrzmy na poniższy przykład.

//przykład łamiący zasadę OCP

public class Square {
    public int sideLength;
}

public class Triangle {
    public int sideLengthA;
    public int sideLengthB;
    public int sideLengthC;
}

public class Calculator {
    public int calculatePerimeter(Object shape) {

        if (shape instanceof Square) {
            return ((Square) shape).sideLength * 4;
        } else if (shape instanceof Triangle) {
            Triangle triangle = (Triangle) shape;
            return triangle.sideLengthA + triangle.sideLengthB + triangle.sideLengthC;
        }

        return 0;
    }
} 

W powyższym przykładzie dodanie nowej figury np. prostokąta wiąże się z koniecznością modyfikacji klasy kalkulatora, co powoduje złamanie zasady otwarty/zamknięty (klasa nie jest otwarta na rozbudowę).
Z pomocą przychodzi nam polimorfizm – każda z klas reprezentujących figury może implementować interfejs Shape oraz metodę liczącą odwód.

//przykład z uwzględnieniem zasady OCP

public interface Shape {
    int perimeter();
}

public class Square  implements Shape {
    public int sideLength;

    @Override
    public int perimeter() {
        return sideLength * 4;
    }
}

public class Triangle implements Shape {
    public int sideLengthA;
    public int sideLengthB;
    public int sideLengthC;

    @Override
    public int perimeter() {
        return sideLengthA + sideLengthB + sideLengthC;
    }
}

public class Calculator {
    public int calculatePerimeter(Shape shape) {
        return shape.perimeter();
    }
} 
Dziedziczenie

Problem bardzo podobnie można rozwiązać przy użyciu dziedziczenia.

//przykład z uwzględnieniem zasady OCP

public abstract class Shape {
    public abstract int perimeter();
}

public class Square  extends Shape {
    public int sideLength;

    @Override
    public int perimeter() {
        return sideLength * 4;
    }
}

public class Triangle extends Shape {
    public int sideLengthA;
    public int sideLengthB;
    public int sideLengthC;

    @Override
    public int perimeter() {
        return sideLengthA + sideLengthB + sideLengthC;
    }
}

public class Calculator {
    public int calculatePerimeter(Shape shape) {
        return shape.perimeter();
    }
} 

Podsumowanie

Zasada Open-Closed jest jedną z pięciu zasad SOLID. Wymaga ona, aby komponent aplikacji był otwarty na rozszerzenie, ale zamknięty na modyfikację.
Aby spełnić ten wymóg możemy użyć polimorfizmu lub dziedziczenia – pierwsza opcja jest zdecydowania lepsza, ponieważ wprowadza do projektu warstwę abstrakcji, która oddziela sprzężenie pomiędzy poszczególnymi klasami.
Dobrym rozwiązaniem jest również zastosowanie niektórych wzorców projektowych (m.in. metoda fabrykująca, metoda szablonowa, strategia czy też budowniczy) – dzięki nim również postępować będziemy zgodnie z OCP, a jednocześnie nasze rozwiązanie zrozumiałe będzie dla innych programistów.
 

Leave a Comment

Your email address will not be published. Required fields are marked *