对函数内部进行参数设置是在编码中经常遇见的一个设计问题,一般情况下,我们会有三种方式。
1、2B程序员(没错这就是我经常用的那种)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| function a_func($option1, $option2)
{
if ($option1) {
//some code
} else {
//some code
}
if ($option2) {
//some code
} else {
//some code
}
}
|
2、普通程序员
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| function b_func($options)
{
if ($options['a']) {
//some code
} else {
//some code
}
if ($options['b']) {
//some code
} else {
//some code
}
}
|
3、文艺的程序员
没错,今儿我就是要讲讲怎么个文艺法.
3.1、对比一下
作为php程序员json_encode 这个函数肯定是再了解不过了,可是大家了解这个函数的第二个参数吗?
1
2
| //像这样
$data_str = json_encode($a, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_UNESCAPED_UNICODE);
|
从 json_encode() 的文档中,我们能得知第二参数的各个选项会对输出来的json字符串有不同的解析方式。
对比一下1和2的用法:
1
2
| a_func(true, false) // 如果不知道函数原型的话根本不知道在干什么。
b_func(['a' => true, 'b' => false]) // 如果是第三方用的话不一定知道还有a和b两个参数,还得去源码中找。
|
3.2、我们如何文艺的设计这样的函数
以我用laravel这么多年的经验来看,内部设计的越精巧复杂,外部用起来就越简单明了。没错,用这种文艺的方法,也会有点复杂。
首先,设计一个解析函数:
1
2
3
4
5
6
7
8
9
10
11
12
| /**
* 解析按位输入的参数
*
* @param int $options 用户选择的参数
* @param int $all_options 所有参数
* @param int $default 默认值
* @return int 解析后的内容
*/
function __parse_bitwise_params($options, $all_options, $default = 0)
{
return $all_options & $options ?: $default;
}
|
看看使用场景:
假如一个用户模块,我们想获取用户的信息,那么其实我们可以这样写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| /**
* 用户模块
*/
class UserModule
{
const USER_RAW = 1;
const USER_STR = 2;
const USER_ARRAY = 4;
/**
* @var User
*/
protected $user;
public function getInfo($options = self::INFO_RAW)
{
$type = __parse_bitwise_params($options, self::USER_RAW | self::USER_STR | self::USER_ARRAY);
switch($type){
case self::USER_RAW:
return $this->user;
break;
case self::USER_STR:
return $this->user->toString();
break;
case self::USER_ARRAY:
return $this->user->toArray();
break;
default:
return $this->user;
}
}
}
|
看到这,各位看官会问了,这不是拖了裤子**嘛!明明传一个数字进来就OK了.
这个问题问的好,因为这种优(wen)雅(yi)的方式肯定不是用于传一种参数的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
| /**
* 用户模块
*/
class UserModule
{
const USER_RAW = 1;
const USER_STR = 2;
const USER_ARRAY = 4;
const USER_MSG_ID = 16;
const USER_MSG_BASE = 32;
const USER_MSG_ALL = 64;
/**
* @var User
*/
protected $user;
public function getInfo($options = self::INFO_RAW)
{
$msg_type = __parse_bitwise_params($options, self::USER_MSG_ID | self::USER_MSG_BASE | self::USER_MSG_ALL);
if ($msg_type == self::USER_MSG_ID) {
return $this->user->id;
}
$type = __parse_bitwise_params($options, self::USER_RAW | self::USER_STR | self::USER_ARRAY);
$get_user_msg = function($opt) {
if ($opt == self::USER_MSG_BASE) {
return array_only($this->user->toArray(), ['id', user_name', 'age']);
} else {
return $this->user->toArray();
}
}
switch($type){
case self::INFO_RAW:
return $this->user;
break;
case self::INFO_STR:
return json_encode($get_user_msg($msg_type));
break;
case self::INFO_ARRAY:
return $get_user_msg($msg_type);
break;
default:
return $this->user;
}
}
}
|
这才是为师的完全体!(不要吐槽那个匿名函数,只是想一个函数写完得了….)
没错,这种写法就是用来传多个参数设计的,那么如果我们使用了这种方案设计代码,外部的调用将会很简单。
1
2
3
4
5
6
7
8
9
10
11
| //获取user_id
$user_id = $userModule->getInfo(UserModule::INFO_MSG_ID);
//获取User模型
$user = $userModule->getInfo(UserModule::INFO_RAW);
//获取用户的信息数组
$user = $userModule->getInfo(UserModule::USER_ARRAY);
//获取用户的基本数据
$user_base = $userModule->getInfo(UserModule::USER_ARRAY | UserModule::USER_MSG_BASE);
|
总结:
对于这种模块的设计,这种方案不一定是最好的,因为设计代码的方式千千万,这只是一块砖,希望能对大家的代码设计带来新的灵感。
原创文章,转载请注明出处链接。