Меню

Принцип открытости закрытости

25.06.2018 - java script, NodeJS, ЯП

The open/closed principle (Принцип открытости закрытости)

Это значит возможно расширять, но нельзя модифицировать.
Что значит расширить?
Это означает Вы можете расширить класс путём наследования, или расширить функцию путём второй функции обёртки.
Что значит закрытый для модификации?
Это означает что Вы не должны изменять класс или функцию, если хотите добавить что-либо.

Посмотрим пример с нарушением этого принципа, а потом реализуем его.

class Person {
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName,
        this.age = age;
    }

    authorize(id) {
        switch(this.type) {
            case "Student" : return this.academicId == id;
            break;
            case "Employee" : return this.employeeId == id;
            break;
            case "Professor" : return this.professorId == id;
            break;
            default: throw new Error ("Type is not defined");
        }
    }

    get type() {
        return this._type;
    }

    set type(value) {
        this._type = value;
    }
}

Что не так с этим кодом? В этом классе метод authorize проверяет тип человека. Это еще никуда не шло, если у Вас всего три типа, ну или чуть больше. Но когда-нибудь в будущем, Вам нужно будет добавить другие типы. Но всё не будет работать относительно нового типа.
В общем, на лицо нарушение принципа Open/Close. Который гласит, что если Вы хотите добавить что-либо в свой класс, то Вы должны расширить его. Но это невозможно реализовать, когда у Вас провека типов происходит таким образом.

Начнём исправлять. Во первых удалим метод authorize и имплементируем классы Student и Employee, которые наследуются от Person. Также укажем проверку на наличие необходимого метода authorize, чтобы разработчики не забыавали добавлять его в своих подклассах.

class Person {
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName,
        this.age = age;
        if (!this.authorize) throw new Error("Person subclass has no implementation for the authorize method");
    }

    get type() {
        return this._type;
    }

    set type(value) {
        this._type = value;
    }
}

class Student extends Person {
    constructor(academicId, firstName, lastName, age) {
        super(firstName, lastName, age);
        this.academicId = academicId;
    }

    authorize(id) {
        return this.academicId == id;
    }
}

class Employee extends Person {
    constructor(employeeId, firstName, lastName, age) {
        super(firstName, lastName, age);
        this.employeeId = employeeId;
    }

    authorize(id) {
        return this.employeeId == id;
    }
}

let emp = new Employee(123322, "John", "Smith", 29);

Как видите, теперь класс Person закрыт от модификаций, а мы можем свободно расширяться от него.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *