Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Design, Quality, Testing > Понимание strategy pattern


Автор: JohnKiedis 14.4.2016, 16:08
Всем привет. 
Получил критику своего кода касательно того, что применяется процедурный стиль написания. Решил уходить от этого. В частности, сейчас разбираю замену if else statement на strategy pattern.
Как один из последних примеров брал http://www.newthinktank.com/2012/08/strategy-design-pattern-tutorial/

По итогу решил сделать вычисление суммы по годовому депозиту - там суть следующая: 
в зависимости от инвестированной клиентом суммы к ней начисляется определенный процент. Проценты были выбраны следующие:
сумма                      процент
меньше 100                   1
меньше 1000                 1.5
меньше 10000                2
больше 10000                3


Применил следующий подход:
- В интерфейсе InterestEvaluation определил метод getEvaluation.
- В классах FirstRate, SecondRate, ThirdRate, FourthRate реализовываю этот InterestEvaluation. В них описал вычисление итоговой суммы для каждого процента.
- В классе SimpleInterest создал сделал методы выбора и вызова методов вычисления итоговой суммы.
- В классах FourthRateEvaluation, ThirdRateEvaluation, SecondRateEvaluation, FirstRateEvaluation написал вызов нужного метода вычисления исходя из введенной суммы инвестиций.

Как итог, я не смог уйти от if else, хотя, возможно, сделал код немного более масштабируемым.

Кто встречался с данным паттерном, подскажите, что бы улучшили/поменяли/переделали и вообще можно ли сказать, что мной здесь был применен этот паттерн?
Спасибо.

Привожу код ниже и на googleDrive - https://drive.google.com/folderview?id=0B6zTmwxI7AkyVFl3TGtmOWVTUkE&usp=sharing


Код

package com.interestevaluation;

import java.util.Scanner;

public class Calculator {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        while (true) {
            try{
                System.out.println("Enter amount to calculate");
                String giveninvest =  scanner.next();

                StringParsingHelper stringParser = new StringParsingHelper();
                double invest = stringParser.getNumericAmount(giveninvest);

                if (invest <= 0)
                    throw new IllegalArgumentException("Illegal parameter. Amount " + invest + " <= 0 ");

                if (invest < 100) {
                    FirstRateEvaluation firstRateEvaluation = new FirstRateEvaluation();
                    System.out.println("the first case: " + firstRateEvaluation.tryGetInterestEvaluation(invest));
                    //example of dynamic change evaluation for particular case
                    firstRateEvaluation.setInterestEvaluation(new ThirdRate());
                    System.out.println("the first case modified: " + firstRateEvaluation.tryGetInterestEvaluation(invest));

                } else if(invest < 1000) {
                    SecondRateEvaluation secondRateEvaluation = new SecondRateEvaluation();
                    System.out.println("the second case: " + secondRateEvaluation.tryGetInterestEvaluation(invest));
                } else if(invest < 10000) {
                    ThirdRateEvaluation thirdRateEvaluation = new ThirdRateEvaluation();
                    System.out.println("the third case: " + thirdRateEvaluation.tryGetInterestEvaluation(invest));
                } else {
                    FourthRateEvaluation fourthRateEvaluation = new FourthRateEvaluation();
                    System.out.println("the fourth case: " + fourthRateEvaluation.tryGetInterestEvaluation(invest));
                }

                System.out.println();
            } catch (IllegalArgumentException ie) {
                System.out.println(ie);
                System.out.println("Bad input value. Try again");
                System.out.println();
            }
        }

    }
}


Код
package com.interestevaluation;

public interface InterestEvaluation {
    double getEvaluation(double invest);
}


class FirstRate implements InterestEvaluation {

    public double getEvaluation(double invest){return invest*0.01 + invest;}
}

class SecondRate implements InterestEvaluation {

    public double getEvaluation(double invest){
        return invest*0.015 + invest;
    }
}

class ThirdRate implements InterestEvaluation {

    public double getEvaluation(double invest){
        return invest*0.02 + invest;
    }
}

class FourthRate implements InterestEvaluation {

    public double getEvaluation(double invest){
        return invest*0.03 + invest;
    }
}





Код
package com.interestevaluation;

public class SimpleInterest {

    public InterestEvaluation interestEvaluation;

    public void setInterestEvaluation(InterestEvaluation newInterestEvaluation){
        interestEvaluation = newInterestEvaluation;
    }

    public double tryGetInterestEvaluation(double invest){
        return interestEvaluation.getEvaluation(invest);
    }

}



Код
package com.interestevaluation;

public class FirstRateEvaluation extends SimpleInterest{

    public FirstRateEvaluation(){
        super();
        interestEvaluation = new FirstRate();
    }
}


Код
package com.interestevaluation;

public class SecondRateEvaluation extends SimpleInterest {

    public SecondRateEvaluation(){
        super();
        interestEvaluation = new SecondRate();
    }
}


Код
package com.interestevaluation;

public class ThirdRateEvaluation extends SimpleInterest{

    public ThirdRateEvaluation(){
        super();
        interestEvaluation = new ThirdRate();
    }
}


Код
package com.interestevaluation;

public class FourthRateEvaluation extends SimpleInterest{

    public FourthRateEvaluation(){
        super();
        interestEvaluation = new FourthRate();
    }
}



Код
package com.interestevaluation;

public class StringParsingHelper {

    protected double getNumericAmount(final String amount) throws NumberFormatException{
        try {
            return Double.parseDouble(amount);
        } catch (NumberFormatException e) {
            throw new NumberFormatException("Failed to parse a non-numeric argument: " + amount);
        }
    }
}



Автор: LSD 14.4.2016, 19:23
В данном случае вообще не нужно создавать 4 класса, достаточно одного с параметрами.

Что касается избавления от if, то тут можно создать фабрику InterestEvaluation-ов в которой:
Или создаем четыре InterestEvaluation: 1, 1.5, 2, 3 и кладем их в TreeMap по минимальной сумме с которой они работают. И дальше берем минимальный слева.
Или (этот вариант мне нравится больше) создаем InterestEvaluation и в качестве параметров туда передаем минимальную сумму.  Дальше добавляем их в коллекцию и сортируем ее по убыванию минимальной суммы. Дальше итерируемся и у каждого InterestEvaluation проверяем isApplicable(amount).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)