Рубрики
Без рубрики

ТВЕРДЫЙ принцип в деталях.

Прежде чем я начну, я хотел бы сказать спасибо соавтору этой статьи Сумье Палу. ТВЕРДЫЙ П… С тегами solid principle, java, softwaredesignpattern, spring.

Прежде чем я начну, я хотел бы сказать спасибо соавтору этой статьи Сумья Пал .

Принцип SOLID – это широко используемый шаблон проектирования программного обеспечения. Есть пять принципов, которые вместе образуют ТВЕРДЫЙ принцип. Он был представлен Робертом К. Мартином в 1988 году, то есть за 8 лет до выпуска Java 1st. Ниже перечислены пять принципов

  • S – Принцип Единой Ответственности
  • O – Открыто для расширения, Закрыто для модификации Принцип
  • Принцип подстановки L – Лискова
  • Принцип разделения I – Интерфейса
  • Принцип Инверсии D – Зависимостей

Принцип Единой Ответственности

S означает Принцип единой ответственности . Это означает, что у одного модуля может быть одна конкретная ответственность, а не много. Мы обычно знаем класс God, что означает, что класс знает много вещей, такой подход нарушает Принцип единой ответственности . Давайте возьмем пример: нам нужно программное обеспечение для медицинского страхования, которое может утверждать поданные заявления. Теперь мы проверяем приведенный ниже класс

package org.example.solidprinciple

class HealthInsurance {

    /**
    * This function will verify that, the documents provide is
    * all good or not good.
    * @return Boolean
    */
    public Boolean isValidClaims() {
        // Function defination goes here.
        return true;
    }    

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public Boolean approve() {
        if(this.isValidClaims()){
            return true;
        }

        return false;
    }

}

Здесь мы можем видеть, что один Медицинское страхование класс, занимающийся проверкой претензий, а также утверждением претензий, здесь Принцип единой ответственности нарушается, класс не должен содержать более одной ответственности с собственной. Теперь давайте изменим код.

package org.example.solidprinciple

class HealthInsurance {

    /**
    * This function will verify that, the documents provide is
    * all good or not good.
    * @return Boolean
    */
    public Boolean isValidClaims() {
        // Function defination goes here.
        return true;
    }

}


class InsuranceApprovalManager {

    private HealthInsurance healthInsurance;

    InsuranceApprovalManager (HealthInsurance healthInsurance) {
        this.healthInsurance = healthInsurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public Boolean approve() {
        if(healthInsurance.isValidClaims()){
            System.out.println("Insurance Claims Successfully Completed.");
            return true;
        }

        System.out.println("Insurance Claims Failed.");
        return false;
    }
}

Теперь мы распределили ответственность на два класса, один Медицинская страховка которая проверит претензию и Insuranceapproval Manager будет одобрен после подтверждения того, что претензии являются хорошими или плохими. Теперь это соответствует принципу Единой ответственности .

Открыт для расширения, закрыт для модификации.

Второй принцип SOLID property открыт для расширения, но закрыт для модификации. Само название объясняет концепцию. Один модуль должен быть спроектирован таким образом, чтобы мы могли добиться другого поведения без изменения кода. СТОП но как? Давайте возьмем тот же пример, который мы видели выше.

package org.example.solidprinciple

class HealthInsurance {

    /**
    * This function will verify that, the documents provide is
    * all good or not good.
    * @return Boolean
    */
    public Boolean isValidClaims() {
        // Function defination goes here.
        return true;
    }

}


class InsuranceApprovalManager {

    private HealthInsurance healthInsurance;

    InsuranceApprovalManager (HealthInsurance healthInsurance) {
        this.healthInsurance = healthInsurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public Boolean approve() {
        if(healthInsurance.isValidClaims()){
            System.out.println("Insurance Claims Successfully Completed.");
            return true;
        }

        System.out.println("Insurance Claims Failed.");
        return false;
    }
}

В этом примере/| Менеджер по утверждению страхования класс зависит от Медицинская страховка , поскольку он принимает объект Медицинская страховка в конструкторе. Теперь, если на картинке появится другая страховка, скажем, Страхование жизни , как страховой менеджер одобрит претензию, тогда нам нужно изменить код. Здесь мы нарушаем второй принцип, потому что мы модифицируем код. Давайте посмотрим, как мы могли бы написать код так, чтобы нам не нужно было изменять код для достижения изменения поведения.

package org.example.solidprinciple

interface Insurance {
    public Boolean isValidClaims();
}

class HealthInsurance implements Insurance{

    /**
    * This function will verify that the documents provide is
    * all good or not good.
    * @return Boolean
    */

    @Override
    public Boolean isValidClaims() {
        // Function defination goes here.
        return true;
    }

}

class LifeInsurance implements Insurance{

    /**
    * This function will verify that the documents provide is
    * all good or not good.
    * @return Boolean
    */

    @Override
    public Boolean isValidClaims() {
        // Function defination goes here.
        return true;
    }

}

class InsuranceApprovalManager {

    private Insurance insurance;

    InsuranceApprovalManager (Insurance insurance) {
        this.insurance = insurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public Boolean approve() {
        if(insurance.isValidClaims()){
            System.out.println("Insurance Claims Successfully Completed.");
            return true;
        }

        System.out.println("Insurance Claims Failed.");
        return false;
    }
}

Здесь мы определили интерфейс с именем Insurance и реализовали его в Медицинское страхование, страхование жизни класс, теперь проверьте InsuranceApprovalManager конструктор

InsuranceApprovalManager (Insurance insurance) {
    this.insurance = insurance;
}

берем ссылочный тип Insurance , чтобы, если в будущем будут добавлены другие типы страхования, мы могли расширить его и использовать. Нет необходимости в изменении текущей структуры кода.

Принцип замещения Лискова

Этот принцип был введен Барбарой Лисковой в 1988 году. В нем говорится, что модуль S является подтипом T, тогда объект T может быть заменен объектом S с изменением его свойства. Это означает, что ссылочный класс должен иметь возможность использовать класс, производный от объекта, не зная об этом. Давайте возьмем пример ниже,

package org.example.solidprinciple

interface Insurance {
    public Boolean isValidClaims();
    public Boolean doctorVerification();
}

class HealthInsurance implements Insurance{

    /**
    * This function will verify that the documents provide is
    * all good or not good.
    * @return Boolean
    */

    @Override
    public Boolean isValidClaims() {
        // Function defination goes here.
        if(this.doctorVerification()) {
            return true;
        }
        return false;
    }

    /**
    * The Claims will check by the doctor whether it is approvable or not.
    * @return Boolean
    */

    @Override
    public Boolean doctorVerification() {
        //Function defincation goes here
        return true;
    }

}

class InsuranceApprovalManager {

    private Insurance insurance;

    InsuranceApprovalManager (Insurance insurance) {
        this.insurance = insurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public Boolean approve() {
        if(insurance.isValidClaims()){
            System.out.println("Insurance Claims Successfully Completed.");
            return true;
        }

        System.out.println("Insurance Claims Failed.");
        return false;
    }
}

Вот, проверьте это Медицинская страховка класс Действительны претензии() эта функция зависит от doctorVerification() . В частности, для этого примера все в порядке. Теперь давайте проверим приведенный ниже пример,

package org.example.solidprinciple

interface Insurance {
    public Boolean isValidClaims();
    public Boolean doctorVerification();
}

class CarInsurance implements Insurance{

    /**
    * This function will verify that the documents provide is
    * all good or not good.
    * @return Boolean
    */

    @Override
    public Boolean isValidClaims() {
        // Function defination goes here.
        if(this.doctorVerification()) {
            return true;
        }
        return false;
    }

    /**
    * The Claims will check by the doctor whether it is approvable or not.
    * @return Boolean
    */

    @Override
    public Boolean doctorVerification() {
        //Function defincation goes here
        return true;
    }

}

class InsuranceApprovalManager {

    private Insurance insurance;

    InsuranceApprovalManager (Insurance insurance) {
        this.insurance = insurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public Boolean approve() {
        if(insurance.isValidClaims()){
            System.out.println("Insurance Claims Successfully Completed.");
            return true;
        }

        System.out.println("Insurance Claims Failed.");
        return false;
    }
}

Здесь мы используем Страхование автомобиля , так что doctor Verification() вообще не нужна, но нам нужно реализовать эту функцию. Эта ситуация нарушает 3-й принцип стека. Как мы можем преодолеть эту ситуацию, давайте посмотрим на приведенный ниже пример.

package org.example.solidprinciple

interface Insurance {
    public Boolean isValidClaims();
}

interface DoctorVerifiableInsurance extends Insurance {
    public Boolean isValidClaims();
    public Boolean doctorVerification();

} 

interface EngineerVerifiableInsurance extends Insurance {
    public Boolean isValidClaims();
    public Boolean engineerVerification();

} 

class HealthInsurance implements DoctorVerifiableInsurance{

    /**
    * This function will verify that the documents provide is
    * all good or not good.
    * @return Boolean
    */

    @Override
    public Boolean isValidClaims() {
        // Function defination goes here.
        if(this.doctorVerification()) {
            return true;
        }
        return false;
    }

    /**
    * The Claims will check by the doctor whether it is approvable or not.
    * @return Boolean
    */

    @Override
    public Boolean doctorVerification() {
        //Function defincation goes here
        return true;
    }

}

class CarInsurance implements EngineerVerifiableInsurance{

    /**
    * This function will verify that the documents provide is
    * all good or not good.
    * @return Boolean
    */

    @Override
    public Boolean isValidClaims() {
        // Function defination goes here.
        if(this.engineerVerification()) {
            return true;
        }
        return false;
    }

    /**
    * The Claims will check by the doctor whether it is approvable or not.
    * @return Boolean
    */

    @Override
    public Boolean engineerVerification() {
        //Function defincation goes here
        return true;
    }

}

class InsuranceApprovalManager {

    private Insurance insurance;

    InsuranceApprovalManager (Insurance insurance) {
        this.insurance = insurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public Boolean approve() {
        if(insurance.isValidClaims()){
            System.out.println("Insurance Claims Successfully Completed.");
            return true;
        }

        System.out.println("Insurance Claims Failed.");
        return false;
    }
}

Здесь мы определили еще два интерфейса ( Страхование, проверяемое инженером, Страхование, проверяемое врачом ), расширяющие базовый интерфейс, и реализовали класс Медицинское страхование, автострахование . Теперь у нас есть правильный поток, в котором нам не нужно внедрять те методы, которые не относятся к конкретной категории страхования.

Принцип разделения Интерфейсов:

Этот принцип является первым принципом, который применяется к интерфейсам вместо классов в SOLID, и он аналогичен принципу единой ответственности. В нем говорится, что “не заставляйте ни одного клиента реализовывать интерфейс, который не имеет к ним отношения”. Здесь ваша главная цель – сосредоточиться на том, чтобы избежать жирного интерфейса и отдать предпочтение множеству небольших клиентских интерфейсов. Вы должны предпочесть множество клиентских интерфейсов, а не один общий интерфейс, и каждый интерфейс должен нести определенную ответственность.

Давайте возьмем пример:

package org.example.solidprinciple

interface Insurance {
    public Boolean isValidClaims();
    public Boolean verification();
    public Boolean lifeInsurance();
    public Boolean healthInsurance();
    public Boolean fireInsurance();
}

class Insuranceclaim implements Insurance{


    @Override
    public Boolean lifeInsurance() {
        if(isValidClaims()){
            return true;
        }
        return false;
    }


    /**
    * This function will verify that the documents provide is
    * all good or not good.
    * @return Boolean
    */
    @Override
    public Boolean isValidClaims() {
        if (verification()){
            return true;
        }
        return false;
    }

    @Override
    public Boolean verification() {
        return true;
    }

    @Override
    public Boolean healthInsurance() {
        return null;
    }

    @Override
    public Boolean fireInsurance() {
        return null;
    }
}


class InsuranceApprovalManager{

    private Insuranceclaim insurance;

    InsuranceApprovalManager(Insuranceclaim insurance){
        this.insurance = insurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public void approve(){
        if(insurance.lifeInsurance()){
            System.out.println("Insurance amount processed successfully");
        }
        else {
            System.out.println("Insurance amount not approved");
        }
    }
}

В приведенном выше примере вы можете видеть, что “InsuranceClaim” должен обеспечивать реализацию методов “health Insurance()” и “Fireinsurance()”, даже если они не требуются. Это является нарушением принципа разделения интерфейса. Такие нарушения влияют на читаемость кода и сбивают программистов с толку. Итак, как решить эту проблему? Вот решение путем разделения интерфейса на несколько интерфейсов, каждый из которых предназначен для определенного поведения. Взгляните на приведенный ниже пример…

package org.example.solidprinciple

interface Insurance {
    public Boolean isValidClaims();
    public Boolean verification();
}

interface LifeInsurace{
    public Boolean lifeInsurance();
}
interface HealthInsurance{
    public Boolean healthInsurance();
}
interface FireInsurance{
    public Boolean fireInsurance();
}

class Insuranceclaim implements  LifeInsurace,Insurance{


    @Override
    public Boolean lifeInsurance() {
        if(isValidClaims()){
            return true;
        }
        return false;
    }

    /**
    * This function will verify that the documents provide is
    * all good or not good.
    * @return Boolean
    */
    @Override
    public Boolean isValidClaims() {
        if (verification()){
            //
            return true;
        }
        return false;
    }

    @Override
    public Boolean verification() {
        return true;
    }

}


class InsuranceApprovalManager{

    private Insuranceclaim insurance;

    InsuranceApprovalManager(Insuranceclaim insurance){
        this.insurance = insurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public void approve(){
        if(insurance.lifeInsurance()){
            System.out.println("Insurance amount processed successfully");
        }
        else {
            System.out.println("Insurance amount not approved");
        }
    }
}

В приведенном выше примере интерфейс “Страхование” разделен на четыре интерфейса, а именно Страхование жизни, Медицинское страхование, страхование от пожара и сам интерфейс “Страхование”. Каждый из которых отвечает за определенное поведение, и также видно, что, когда “InsuranceClaim” реализует “Страхование жизни” и “Страхование”, два других интерфейса не обязательно должны там присутствовать. Таким образом, измененный код более удобочитаем и менее подвержен изменениям из-за разделения интерфейсов.

Принцип Инверсии зависимостей

Общая идея этого принципа столь же проста, сколь и важна: модули высокого уровня, которые обеспечивают сложную логику, должны быть легко повторно использованы и не подвержены изменениям в модулях низкого уровня, которые предоставляют полезные функции. Чтобы достичь этого, вам необходимо ввести абстракцию, которая отделяет высокоуровневые и низкоуровневые модули друг от друга.

Основываясь на этой идее, определение принципа инверсии зависимостей Робертом К. Мартином состоит из двух частей:

1) Модули высокого уровня не должны зависеть от модулей низкого уровня. И то, и другое должно зависеть от абстракций. 2) Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

package org.example.solidprinciple

class Insurance{

    public Boolean isValidClaims(){
        return true;
    }

    /**
    * The Claims will check by the doctor whether it is approvable or not.
    * @return Boolean
    */
    public Boolean approval(){
        if(DoctorvVerification()){
            return true;
        }
        return false;
    }


    public Boolean DoctorvVerification(){
        if(isValidClaims()){
            return true;
        }
        return false;
    }
}

class ManageHeathInsuranceClaim {

    private Insurance insurance;

    ManageHeathInsuranceClaim(Insurance insurance){
        this.insurance = insurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public void approved(){
        if(insurance.approval()){
            System.out.println("Insurance Claim processed successfully");
        }
        System.out.println("Claim couldn't be processed");
    }
}

В приведенном выше примере видно, что Требование о медицинском страховании менеджера зависит от страхового модуля, который является модулем высокого уровня, зависит от модуля низкого уровня. Но это нарушает первое свойство принципа инверсии зависимостей. Также, если кто-то хочет добавить какую-то другую страховку, например Страхование имущества, для этого необходимо изменить класс страхования. Чтобы решить эту проблему, нам нужно реализовать интерфейс. Взгляните на приведенный ниже пример…

package org.example.solidprinciple

interface Insurance{
    public Boolean isValidClaims();
    public Boolean approval();
}

class HealthInsuranceManager implements Insurance {

    public Boolean isValidClaims() {
        return true;
    }

    public Boolean approval() {
        if (doctorVerification()) {
            return true;
        }
        return false;
    }


    /**
    * The Claims will check by the doctor whether it is approvable or not.
    * @return Boolean
    */
    public Boolean doctorVerification() {
        if (isValidClaims()) {
            return true;
        }
        return false;
    }
}

class PropertyInsuranceManager implements Insurance{

   @Override
    public Boolean isValidClaims() {
        return true;
    }

    public Boolean approval(){
        if(proertyVerification()){
            return true;
        }
        return false;
    }


    /**
    * The Claims will check by the govt. whether it is approvable or not.
    * @return Boolean
    */
    public Boolean proertyVerification(){
        if(isValidClaims()){
            return true;
        }
        return false;
    }
}


class ManageInsuranceClaim{

    private Insurance insurance;

    ManageInsuranceClaim(Insurance insurance){
        this.insurance = insurance;
    }

    /**
    * This function will check wheather claims are valid or not the 
    * approved the claims.
    * @return Boolean
    */
    public void approved(){
        if(insurance.approval()){
            System.out.println("Insurance Claim processed successfully");
        }
        System.out.println("Claim couldn't be processed");
    }
}

В измененном коде высокоуровневый модуль в зависимости от абстракции (страхование интерфейса) вместо низкоуровневого модуля (Healthinsurancemanager, PropertyInsuranceManager), а также низкоуровневый зависит от абстракции, что означает, что любой может добавить другой страховой модуль и нет необходимости изменять код. Этот код полностью удовлетворяет всем свойствам принципа инверсии зависимостей.

Надеюсь, мы сможем предоставить вам подробные знания о солидной собственности.

Оригинал: “https://dev.to/subhendumondal/solid-principle-in-details-1mka”