1. 程式人生 > 實用技巧 >策略模式在Thread和Runnable中的應用分析

策略模式在Thread和Runnable中的應用分析

策略模式在Thread和Runnable中的應用分析

這裡以實現個人所得稅的計算功能為例,一步步來模擬Runnable的樣子來優化程式碼:

模板方法

/**
 * @program: ThreadDemo
 * @description: 計算稅率:工資*0.1 + 獎金*0.15
 * @author: [email protected]
 * @create: 2020-08-28
 */
public class TaxCalculatorMain {
    public static void main(String[] args) {
        TaxCalculator taxCalculator = new TaxCalculator(10000d, 2000d) {
            @Override
            protected double calcTax() {
                return getSalary() * 0.1 + getBonus() * 0.15;
            }
        };
        double tax = taxCalculator.calculate();
        System.out.println(tax);
    }
}
/**
 * @program: ThreadDemo
 * @description: 個人所得稅計算器
 * @author: [email protected]
 * @create: 2020-08-28
 */
public class TaxCalculator {
    // 薪水
    private final double salary;
    // 獎金
    private final double bonus;

    public TaxCalculator(double salary, double bonus) {
        this.salary = salary;
        this.bonus = bonus;
    }

    public double getSalary() {
        return salary;
    }

    public double getBonus() {
        return bonus;
    }

    protected double calcTax() {
        return 0.00;
    }

    public double calculate() {
        return calcTax();
    }
}

calculate可以理解為Thread的start方法,他return calcTax();可以理解為start()呼叫Runnable的run方法。

這樣實現個人所得稅計算器是沒問題的,但是如果在真實的商業應用中就得去改對應介面的程式碼,這從設計開閉原則來說就不符合了,所以這裡抽象一個計算稅率的接口出來專門來做這個計算,改造程式碼如下:

首先我們抽象一個計算稅率的接口出來專門來做計算:

@FunctionalInterface
public interface CalculatorStrategy {
    /**
     *
     * @param salary 薪水
     * @param bonus 獎金
     * @return 稅收
     */
    double calculate(double salary, double bonus);
}

接下來我們把具體實現流程放在實現類中:

/**
 * @program: ThreadDemo
 * @description: 計算稅率:工資*0.1 + 獎金*0.15
 * @author: [email protected]
 * @create: 2020-08-28
 */
public class SimpleCalculatorStrategy implements  CalculatorStrategy {
    private final static double SALARY_RATE = 0.1;
    private final static double BONUS_RATE = 0.15;

    @Override
    public double calculate(double salary, double bonus) {
        return salary * SALARY_RATE + bonus * BONUS_RATE;
    }
}

修改main方法如下:

/**
 * @program: ThreadDemo
 * @description: 計算稅率:工資*0.1 + 獎金*0.15
 * @author: [email protected]
 * @create: 2020-08-28
 */
public class TaxCalculatorMain {
    public static void main(String[] args) {
        //使用摸板方法
        /*TaxCalculator taxCalculator = new TaxCalculator(10000d, 2000d) {
            @Override
            protected double calcTax() {
                return getSalary() * 0.1 + getBonus() * 0.15;
            }
        };
        double tax = taxCalculator.calculate();
        System.out.println(tax);*/
        //使用策略模式
        CalculatorStrategy strategy = new SimpleCalculatorStrategy();
        TaxCalculator calculator = new TaxCalculator(10000d, 2000d,strategy);
        double tex = calculator.calculate();
        System.out.println(tex);
    }
}

計算呼叫演算法的類如下:

/**
 * @program: ThreadDemo
 * @description: 個人所得稅計算器
 * @author: [email protected]
 * @create: 2020-08-28
 */
public class TaxCalculator {
    // 薪水
    private final double salary;
    // 獎金
    private final double bonus;

    //計算策略類
    private CalculatorStrategy calculatorStrategy;

    public TaxCalculator(double salary, double bonus, CalculatorStrategy calculatorStrategy) {
        this.salary = salary;
        this.bonus = bonus;
        this.calculatorStrategy = calculatorStrategy;
    }

    public double getSalary() {
        return salary;
    }

    public double getBonus() {
        return bonus;
    }

    protected double calcTax() {
        return calculatorStrategy.calculate(salary, bonus);
    }

    public double calculate() {
        return calcTax();
    }
}

這裡其實主要增加了 CalculatorStrategy物件和calcTax的實現呼叫了實現演算法介面的實現類。

main方法的CalculatorStrategy 就相當於Thread的Runnable

接下來我們加入java8的Lambda表示式來精簡一下程式碼:

public class TaxCalculatorMain {
    public static void main(String[] args) {
       //使用java8的Lambda表示式
        TaxCalculator calculator = new TaxCalculator(10000d, 2000d, (s, b) -> s * 0.1 + b * 0.15);
        System.out.println(calculator.calculate());
    }
}

可以看到程式碼精簡很多。