staff

 

 

 

该例中,策略模式用来封装算法。但在实践中,可以用它来封装几乎任何类型的规则,只要分析不同规则之间的相同点,抽象出
抽象类或接口。然后再基于抽象类或接口进行编程


 Java中Comparator接口就是用的策略模式,来描述 “比较的策略”,还有函数式接口也是用的策略模式,Suplier,Consumer等

 需求:要对实体类进行排序操作,根据实体类的属性值,排序方式有多种,比如Person类,可以按身高排序,按体重排序

 

排序类:Sorter    用Comparator来表达比较的方式

package strategy;

import java.util.Comparator;

public class Sorter<T> {
    public void sort(T[] arr, Comparator<T> comparator) {
        //假设用选择排序
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                //交换数据
                if (comparator.compare(arr[i], arr[j]) > 0) {
                    T tmp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = tmp;
                }
            }
        }
        //打印排序结果
        for(T t:arr){
            System.out.print(t+"   ");
        }
        System.out.println();
    }
}

 

main方法:

package strategy;

public class Main {
    public static void main(String[] args) {
        Person[] personArr = {new Person(165, 70),
                new Person(172, 65), new Person(175, 60)};
        Sorter<Person> sorter = new Sorter<>();
        //按体重排序
        sorter.sort(personArr, (o1, o2) -> {
            if (o1.getHeight() > o2.getHeight()) return 1;
            else if (o1.getHeight() < o2.getHeight()) return -1;
            return 0;
        });
        //按身高排序
        sorter.sort(personArr, (o1, o2) -> {
            if (o1.getWeight() > o2.getWeight()) return 1;
            else if (o1.getWeight() < o2.getWeight()) return -1;
            return 0;
        });
    }
}

 

 

实体类:Person

package strategy;

public class Person {
    private int height;
    private int weight;

    public Person(){}

    public Person(int height, int weight) {
        this.height = height;
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Person{" +
                "height=" + height +
                ", weight=" + weight +
                \'}\';
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }
}

 

 

 

 

 

 

 

 

 

 

 

 


 

 

策略模式:它定义了算法家族,分别封装起来,让它们之间可以互相替换
此模式让算法的变化,不会影响到使用算法的客户。

策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的
工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用
算法类之间的耦合。
策略模式的Strategy类层次为Context定义了一些列的可供重用的算法或行为。继承有助于析
取出这些算法中的公共功能。
策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
用法:
测试模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则
只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种
变化的可能性。

import math

class CashStrategy:
    \'\'\'
    收费算法策略类
    \'\'\'
    def algorithm_cash(self, money):
        raise NotImplementedError

class CashNormal(CashStrategy):
    \'\'\'
    正常收费算法
    \'\'\'
    def algorithm_cash(self, money):
        return money

class CashRebate(CashStrategy):
    \'\'\'
    打折收费算法
    \'\'\'
    def __init__(self, rate):
        self.rate = rate
    def algorithm_cash(self, money):
        return money * self.rate

class CashReturn(CashStrategy):
    \'\'\'
    返利收费算法,初始化时必须要输入返利条件和返利值,
    比如满300返100,则money_condition为300,money_return为100
    \'\'\'
    def __init__(self, money_condition, money_return):
        self.money_condition = money_condition
        self.money_return = money_return
    def algorithm_cash(self, money):
        result = money
        if money >= self.money_condition:
            result = money - math.floor(money / self.money_condition) * self.money_return
        return result

class Context:
    \'\'\'
    上下文,维护一个对Strategy策略对象的引用
    \'\'\'
    def __init__(self, type):
        cash_strategy = None
        if type == \'正常收费\':
            cash_strategy = CashNormal()
        elif type == \'满300返100\':
            cash_strategy = CashReturn(300, 100)
        elif type == \'打8折\':
            cash_strategy = CashRebate(0.8)
        self.cash_strategy = cash_strategy
    def get_result(self, money):
        return self.cash_strategy.algorithm_cash(money)


if __name__ == \'__main__\':
    c = Context(\'满300返100\')
    result = c.get_result(800)
    print(result)
\'\'\'
600
\'\'\'
策略模式例子

 


 第一版:Context里:包装算法对象,Context的方法:包装算法对象的方法

class Algorithm:
    def get_result(self, money):
        raise NotImplementedError()
class AlgorithmNormal(Algorithm):
    \'\'\'
    正常收费算法
    \'\'\'
    def get_result(self, money):
        return money

class AlgorithmRebate(Algorithm):
    \'\'\'
    打折收费算法
    \'\'\'
    def __init__(self, rate):
        self.rate = rate
    def get_result(self, money):
        return money * self.rate

class Context:
    def __init__(self, algorithm_obj):
        self.algorithm_obj = algorithm_obj
    def get_pay(self, money):
        return self.algorithm_obj.get_result(money)

if __name__ == \'__main__\':
    normal = Context(AlgorithmNormal())
    pay = normal.get_pay(300)
    print(pay)

    rebate = Context(AlgorithmRebate(0.8))
    pay = rebate.get_pay(300)
    print(pay)

第二版:Context里:包装算法类,Context的方法:包装算法类的静态方法,注意参数用 *args **kwargs

class AlgorithmNormal:
    \'\'\'
    正常收费算法
    \'\'\'
    @staticmethod
    def get_result(money):
        return money

class AlgorithmRebate:
    \'\'\'
    打折收费算法
    \'\'\'
    @staticmethod
    def get_result(money, rate):
        return money * rate

class Context:
    def __init__(self, algorithm_cls):
        self.algorithm_cls = algorithm_cls
    def get_pay(self, *args, **kwargs):
        return self.algorithm_cls.get_result(*args, **kwargs)

if __name__ == \'__main__\':
    normal = Context(AlgorithmNormal)
    pay = normal.get_pay(300)
    print(pay)

    rebate = Context(AlgorithmRebate)
    pay = rebate.get_pay(300, 0.8)
    print(pay)

第三版:Context里:包装算法方法本身,Context的方法里:包装算法方法的调用,注意参数用 *args **kwargs

def get_result_normal(money):
        return money

def get_result_rebate(money, rate):
        return money * rate

class Context:
    def __init__(self, algorithm_func):
        self.algorithm_func = algorithm_func
    def get_pay(self, *args, **kwargs):
        return self.algorithm_func(*args, **kwargs)

if __name__ == \'__main__\':
    normal = Context(get_result_normal)
    pay = normal.get_pay(300)
    print(pay)

    rebate = Context(get_result_rebate)
    pay = rebate.get_pay(300, 0.8)
    print(pay)

第四版:Context里:包装算法方法本身,取消Context的方法,客户端直接调用Context的对象

def get_result_normal(money):
        return money

def get_result_rebate(money, rate):
        return money * rate

class Context:
    def __init__(self, algorithm_func):
        self.algorithm_func = algorithm_func

if __name__ == \'__main__\':
    normal = Context(get_result_normal)
    pay = normal.algorithm_func(300)
    print(pay)

    rebate = Context(get_result_rebate)
    pay = rebate.algorithm_func(300, 0.8)
    print(pay)

 

分类:

技术点:

相关文章: