委托的好处
1、业务背景
技术为业务而生,技术为解决业务问题而存在,技术脱离业务就变得没有价值,我们在探讨某一个技术带来的价值时,都需要有一定的业务背景作为前提。我们先来看如下需求背景:
定义一个学生类,属性包含学生姓名、学号、年龄、创建时间,行为包含学生可以使用正确的方式对不同国家的人打招呼,如对中国人打招呼为:张三,你好!对美国人打招呼为Jack hello!
2、解决方式1,使用传统的分支逻辑判断
示例代码及调用方式:
1 public class Student
2 {
10 public string StuName { get; set; }
11
12 public string StuNum { get; set; }
13
14 public int Age { get; set; }
15
16 public DateTime CreateTime { get; set; }
17
18 /// <summary>
19 /// 对不同国家的人说hello,每个国家的表达方式不一样
20 /// </summary>
21 /// <param name="name"></param>
22 /// <param name="peopleType"></param>
23 public void SayHello(string name, PeopleType peopleType) {
25 Console.WriteLine($"{this.StuName }开始打招呼");
27 switch (peopleType)
28 {
29 case PeopleType.Chinese:
30 Console.WriteLine($"{name},你好!");
31 break;
32 case PeopleType.American:
33 Console.WriteLine($"{name},hello");
34 break;
35 default:
36 throw new Exception("enum PeopleType exception");
37 }
38 }
39 }
1 {
2 Student student = new Student() {
3 StuName = "wjl",
4 StuNum = "14216600010",
5 Age = 18,
6 CreateTime = DateTime.Now
7 };
8 student.SayHello("张三", PeopleType.Chinese);
9 student.SayHello("jack", PeopleType.American);
10 }
该种方式的优缺点:
假如业务有变动,需要增加一个对马来西亚国家的人打招呼的功能,就得在枚举中增加马来西亚的枚举类型,在SayHello方法中增加一个对马来西亚类型的分支逻辑判断,这种方式导致的问题就是任意分支变化都得修改方法,代码很不稳定,如果业务逻辑更复杂变得难以维护。但这种方式增加公共逻辑方便,如:Console.WriteLine($"{this.StuName }开始打招呼");
3、解决方式2,针对对不同类型国家的人,定义不同的方法
示例代码及调用方式:
1 public class Student
2 {
4 public enum PeopleType
5 {
6 Chinese = 1,
7 American = 2
8 }
9
10 public string StuName { get; set; }
11
12 public string StuNum { get; set; }
13
14 public int Age { get; set; }
15
16 public DateTime CreateTime { get; set; }
17
18 /// <summary>
19 /// 对中国人说你好
20 /// </summary>
21 /// <param name="name"></param>
22 public void SayHelloChinese(string name)
23 {
24 Console.WriteLine($"{this.StuName }开始打招呼");
25 Console.WriteLine($"{name},你好!");
26 }
27
28 /// <summary>
29 /// 对美国人说你好
30 /// </summary>
31 /// <param name="name"></param>
32 public void SayHelloAmerican(string name)
33 {
34 Console.WriteLine($"{this.StuName }开始打招呼");
35 Console.WriteLine($"{name},hello");
36 }
37 }
1 {
2 Console.WriteLine("调用说你好的功能,方式2");
3 Student student = new Student()
4 {
5 StuName = "wjl",
6 StuNum = "14216600010",
7 Age = 18,
8 CreateTime = DateTime.Now
9 };
10 student.SayHelloChinese("张三");
11 student.SayHelloAmerican("jack");
12 }
该种方式的优缺点:
假如业务变动,需要增加一个对马来西亚国家的人打招呼的功能,就要增加一个方法,不影响别的方法。但这种方式增加公共逻辑会导致多个方法有很多重复代码,如上述代码中的Console.WriteLine($"{this.StuName }开始打招呼");,这种方式不利于代码复用,如果要修改这些公共逻辑或者增加更多的公共逻辑,需要修改的地方较多,不利于维护。
4、解决方式3,利用委托,将不同的业务逻辑分离出去,相同的业务逻辑提取出来
示例代码及调用方式:
1 public class Student
2 {
3 public delegate void SayHelloDelegate(string name);
4 public string StuName { get; set; }
5 public string StuNum { get; set; }
6 public int Age { get; set; }
7 public DateTime CreateTime { get; set; }
8 public void SayHelloPerfect(string name, SayHelloDelegate sayHello ) {
9 Console.WriteLine($"{this.StuName }开始打招呼");
10 sayHello.Invoke(name);
11 }
12 #region 方式2
13 /// <summary>
14 /// 对中国人说你好
15 /// </summary>
16 /// <param name="name"></param>
17 public void SayHelloChinese(string name)
18 {
19 Console.WriteLine($"{name},你好!");
20 }
21 /// <summary>
22 /// 对美国人说你好
23 /// </summary>
24 /// <param name="name"></param>
25 public void SayHelloAmerican(string name)
26 {
27 Console.WriteLine($"{name},hello");
28 }
29 #endregion
30 }
1 {
2 Student student = new Student()
3 {
4 StuName = "wjl",
5 StuNum = "14216600010",
6 Age = 18,
7 CreateTime = DateTime.Now
8 };
9 SayHelloDelegate method1 = student.SayHelloChinese;
10 student.SayHelloPerfect("张三", method1);
13 SayHelloDelegate method2 = student.SayHelloAmerican;
14 student.SayHelloPerfect("Jack", method2);
15 }
该种方式的优缺点:
这种处理方式将逻辑作为参数传递,将不同的业务逻辑分离出去,交给调用者传递,保证了现有方法的稳定,增加公共逻辑(Console.WriteLine($"{this.StuName }开始打招呼");)方便,实现了代码重用,对不同的逻辑分离维护简单,实现逻辑解耦,鱼和熊掌兼得,方便维护升级。相同的东西用一个方法实现,不同的各自去写,然后通过委托组合,加方法满足不同的场景,如果业务逻辑或者说方法特别复杂,就推荐用这种方式去处理。
- Codeforces 626B Cards(模拟+规律)
- Android 5.0屏幕录制漏洞(CVE-2015-3878)威胁预警
- Codeforces 626A Robot Sequence(模拟)
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)【莫队算法裸题&&学习笔记】
- [接口测试 - 基础篇] 01 你应该了解的协议基础
- Uva - 12050 Palindrome Numbers【数论】
- [接口测试 - http.client篇] 14 源码初探及其工作机制分析
- 51Nod 1277 字符串中的最大值(KMP,裸题)
- Codeforces Round #345 (Div. 2)【A.模拟,B,暴力,C,STL,容斥原理】
- 07.移动先行之谁主沉浮----控件之轮流轰炸——布局类控件
- BZOJ 1411&&Vijos 1544 : [ZJOI2009]硬币游戏【递推,快速幂】
- UVa 10341 - Solve It【经典二分,单调性求解】
- UVa 11461 - Square Numbers【数学,暴力】
- BZOJ 3097: Hash Killer I【构造题,思维题】
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Dynamic Programming - 72. Edit Distance
- Dynamic Programming - 64. Minimum Path Sum
- Dynamic Programming - 322. Coin Change
- Dynamic Programming - 279. Perfect Squares
- Dynamic Programming - 120. Triangle
- Dynamic Programming - 63. Unique Paths II
- Tree - 109. Convert Sorted List to Binary Search Tree
- Tree - 108. Convert Sorted Array to Binary Search Tree Easy
- Tree - 236. Lowest Common Ancestor of a Binary Tree
- Tree - 235. Lowest Common Ancestor of a Binary Search Tree
- Tree - 98. Validate Binary Search Tree
- Tree - 199. Binary Tree Right Side View
- Tree - 103. Binary Tree Zigzag Level Order Traversal
- Tree - 107. Binary Tree Level Order Traversal II
- Trie - 212. Word Search II