通过状态模式减少 if else

2017-03-02 18:16:51 +08:00
 twogoods
![]( http://p1.bqimg.com/567571/61a619009daaefa8.jpg)
我理解的状态模式会把 if else 里的具体逻辑通过状态对象抽象出来,如果有一个场景是读配置文件中的一个值,根据值做不同的逻辑,如果可取的值有 5 个,那么状态模式一定可以减少 if else 的数量吗?
4030 次点击
所在节点    程序员
14 条回复
KIDJourney
2017-03-02 19:36:29 +08:00
count = 1
if xxxx:
count += 1
if xxxx:
count += 1

if count != 2:
return False
sumhat
2017-03-02 19:53:33 +08:00
map: {
"state1": func1,
"state2": func2,
"state3": func3,
"state4": func4,
"state5": func5,
}

processState(state) {
func = map[state]
func()
}

完全没有 if/else
twogoods
2017-03-02 20:07:59 +08:00
@sumhat 您这剑走偏锋,没毛病😂
cafdd239
2017-03-02 20:19:33 +08:00
@twogoods 这一点也不偏。。。。
aleen42
2017-03-02 20:32:55 +08:00
Use a lookup table like @sumhat
aleen42
2017-03-02 20:34:17 +08:00
@sumhat 但是直接用数组,访问时会性能更快

var map = [null, func1, func2, func3, func4, func5];
ryd994
2017-03-03 06:18:18 +08:00
说主题,这里的 if-return 其实不会提高性能
看起来是少了 if-else ,可也别把编译器当傻子,编译器早就知道优化这种情况了。
if-return 的用法主要是用在输入验证的时候,可以 if (illegal) return error ,在要验证的内容很多的情况下,可以有效减少嵌套层数,提高代码可读性。和性能没半毛钱关系。

另外这种情况 C/C++代码用的比较多。
Python 里面楼上用函数表就是标准做法,一点也不偏,这就是状态模式的一种表达法。如果平时用状态模式考虑问题,这种表达是很自然的。你必须理解一点:程序也是数据。
C 里面用函数指针也可以实现,不知道为啥不多见。可能因为过程语言本身的习惯,以及函数指针没用起来那么方便。毕竟 C 里面还要自己处理越界,不能依赖 runtime 检查。


@aleen42 解释型语言就别纠结这种零碎性能了,谁知道 runtime 开销多大。可维护性最重要。不是所有判断条件都是整数的。比如写个 HTTP 后端,完全可以直接用字符串做 method 的选择。
heiher
2017-03-03 08:43:39 +08:00
@ryd994 C 程序之所以减少使用函数指针,我想可能因为是从寄存器跳转的分支预测率是较其它低的。
zhjits
2017-03-03 10:21:12 +08:00
void branch_1(){ do_something(); }
void branch_2(){ do_some_other_thing(); }
void (*selection[])() = { branch_1, branch_2 };
// ...
bool condition = a > b;
(*selection[condition])();

听说不要用 if ?
twogoods
2017-03-03 10:36:15 +08:00
@ryd994 hashtable 的方式看着其实跟 switch 很像呀
switch(state): {
case "state1": func1,
case "state2": func2,
case "state3": func3,
case "state4": func4,
case "state5": func5,
}
有 O(1)和 O(n)的差别,当然维护性上看, table 方式会好一点,但具体逻辑抽象成 func1,func2 后,感觉也没那么大了呀
如果判断条件是整数,字符串也行, switch 本质上只是写法不一样,还是要挨个遍历没减少 if else, table 的方式说减少 if else 能是能接受,总感觉怪。我刚看设计模式,感觉状态模式就是那几个 func1 , func2 的抽象,你总是要根据一个判断条件来确定是哪个 func ,可能我有点钻代码上一代要减少 if else 这个牛角尖了...
ryd994
2017-03-03 14:58:53 +08:00
@twogoods 不是 O(n) https://wiki.python.org/moin/TimeComplexity#dict
你要明白 dict 是带索引结构的,所以可以快
要避免多层嵌套 if ,否则代码看都看不清。对 Python 尤为重要,毕竟不是所有人都身上带着游标卡尺的。
还是那句话, if 判断从性能上来讲是无法消除的,但可以消除多层嵌套,提高代码可读性。
另外,我说可以直接用 string 是这种:
if method==“ GET ”: do_get ()
elif method=="POST" do_post()
……
这种用 dict 最合适
ryd994
2017-03-03 15:00:02 +08:00
@twogoods 状态模式用适合实现那些可以用状态机简单描述的算法
bp0
2017-03-03 15:03:38 +08:00
简单的说,使用查表法实现有限状态机。
padeoe
2017-03-03 17:33:06 +08:00
状态模式是为了解决复杂对象的描述困难的吧,可以减少条件分支。楼主的需求应该是策略模式吧,是无法消灭条件分支的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/344405

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX