需求

考虑一种场景,后台给客户端下发规则,客户端根据规则判断是否匹配,作相应处理。例如后台给客户端下发如下规则:

{
  "key": "env_temperature",
  "level": 5,
  "logic": "gt",
  "presetValue": 30
}

则表示当温度大于30时候触发规则,触发后可能播放声音,开启警示灯等。当然触发规则后的操作也可以写入到规则中

预备知识

  • python中内建函数的any和all,接收一个可迭代类型(如数组或者元组),对于any如果内部元素任何一个为True,则返回True;对于all,如果内部元素都为True则返回True,否则返回False。如:
>>> any([True, False])
True
>>> all((True, False,))
False

  • lambda表达式传递,类似Java的函数式接口,是行为参数化的一种形式,例如:
>>> def do_express(express, x, y):
...     print express(x, y)
...     
>>> do_express(lambda x, y : x == y, 1 , 2)
False
>>> do_express(lambda x, y : x == y, 'abc' , 'abc')
True
  • 将数组转换为另一个数组,是python中一种写法,有点类似流处理,例如我们需要将数组中所有数加10
>>> [i + 10 for i in range(7)]
[10, 11, 12, 13, 14, 15, 16]

使用逻辑引擎

def check(logic, preset_value, collect_value):
    logic = logic.upper()
    compare_values = []
    if isinstance(collect_value, list) or isinstance(collect_value, tuple):
        compare_values.extend(collect_value)
    else:
        compare_values.append(collect_value)

    if logic == "GT":
        return do_check_int(any, lambda x, y: x > y, compare_values, preset_value)
    if logic == "GE":
        return do_check_int(any, lambda x, y: x >= y, compare_values, preset_value)
    if logic == "LT":
        return do_check_int(any, lambda x, y: x < y, compare_values, preset_value)
    if logic == "LE":
        return do_check_int(any, lambda x, y: x <= y, compare_values, preset_value)
    if logic == "EQ":
        return do_check_int(any, lambda x, y: x == y, compare_values, preset_value)
    if logic == "NE":
        return do_check_str(any, lambda x, y: x != y, compare_values, preset_value)
    if logic == "CONTAINS":
        return do_check_str(any, lambda x, y: y in x, compare_values, preset_value)
    if logic == "ANYSTARTWITH":
        return do_check_str(any, lambda x, y: x.startswith(y), compare_values, preset_value)
    if logic == "ALLSTARTWITH":
        return do_check_str(all, lambda x, y: x.startswith(y), compare_values, preset_value)

    return False


def do_check_int(checking, express, compare_values, preset_value):
    return do_check(checking, express, compare_values, preset_value, int)


def do_check_str(checking, express, compare_values, preset_value):
    return do_check(checking, express, compare_values, preset_value, str)


def do_check(checking, express, compare_values, preset_value, convert):
    return checking([express(convert(x), convert(preset_value)) for x in compare_values])

测试

>>> check('gt', 1, 2)
True
>>> check('gt', 1, 0)
False
>>> check('eq', 1, 0)
False
>>> check('eq', 1, 1)
True
>>> check('allstartwith', 1, (10,2,) )
False
>>> check('anystartwith', 1, (10,2,) )
True

总结

通过上述我们实现了简单的逻辑引擎,在此基础上我们也可实现一些复杂的规则逻辑,Java中的函数式接口可以用于其中