extField!
5 @IBOutlet var secondNumberTextField: UITextField!
6 @IBOutlet var resultTextField: UITextField!
7
8 override func viewDidLoad() {
9 super.viewDidLoad()
10 }
11
12 //获取第一个输入框的值
13 func getFirstNumber() -> String {
14 return firstNumberTextField.text!
15 }
16
17 //获取第二个输入框的值
18 func getSecondNumber() -> String {
19 return secondNumberTextField.text!
20 }
21
22 //加数与被加数中的值改变时会调用的方法
23 @IBAction func textFieldChange(sender: AnyObject) {
24 self.resultTextField.text = calculate(getFirstNumber(), second: getSecondNumber())
25 }
26
27
28 //计算两个数的值
29 func calculate(first: String, second: String) -> String {
30 return String(stringToInt(first) + stringToInt(second))
31 }
32
33 //将字符串安全的转变成整数的函数
34 func stringToInt(str: String) -> Int {
35 guard let result = Int(str) else {
36 return 0
37 }
38 return result
39 }
40 }
2.对上述代码进行分析并重构
因为代码比较简单,所以很容易进行分析。在上述UI代码中,我们很清楚的看到后两个函数,也就是calculate()与stringToInt()函数是数据处理的部分,只依赖于数据,与UI关系不是很大,所以我们可以使用复制“被监测数据”规则将该段业务逻辑代码进行提取重构。重构后UI以及UI对外的工作方式不变。
下方的Calculate类就是我们提取的数据业务类,负责处理数据。在该类中我们创建了三个属性来与UI中的输入框进行对应,这也就是所说的复制“被监测的数据”。因为和也就是resultNumber是由firstNumber和SecondNumber计算而来的,所以我们就把resultNumber定义成了计算属性,而firstNumber和secondNumber为存储属性。并为存储属性提供setter方法。在Calculate类的构造函数中,我们为两个值指定了初始化数据也就是“0”。最下方的那两个函数就是我们从UI中直接拷贝过来的数据,一点没有修改,也是可以工作的,因为这部分代码只依赖于数据,而不依赖于UI。
创建为相应的业务逻辑处理类并提取完业务逻辑后,我们需要将业务逻辑中的数据,也就是复制过来的数据与UI中的数据提供者进行绑定,并返回计算结果。下方红框中就是我们要修改的部分,在UI中我们删除掉处理业务数据的代码,然后创建也给Calculate对象,并在相应的事件监听的方法中更新Calculate对象中的数据。如下所示
七、Change Unidirectional Association to Bidirectional(将单向关联改为双向关联)
要介绍本部分呢,我想引用本篇博文中第(三)部分是实例。因为在第三部分的实例中Customer与Order的关系是单向关联的,也就是说Order引用了Customer, 而Customer没有引用Order。换句话说,我们知道这个订单是谁的,但你不知道只通过用户你是无法知道他有多少订单的。为了只通过用户我们就能知道该用户有多少订单,那么我们需要使用到“将单向关联改为双向关联”这条规则。
1. 在Customer类中添加上指向Order类的链
因为Customer没有指向Order类的链,所以我们不能获取到该用户有多少订单,现在我们就要添加上这条链。将单向关联改为双向关联,具体做法是在Customer中添加一个数组,该数组中存储的就是该用户所拥有的订单。这个数组就是我们添加的链。数组如下:
1 //添加与Order关联的链,一个用户有多个订单
2 private var orders:Array<Order> = []
在Customer中值只添加数组也是不行的呢,根据之前提到的重构规则,我们要为数组封装相应的操作方法的,下方就是我们要在Customer中添加的操作数组的方法。具体代码如下所示:
1 //====================添加==================
2 func addOrder(order: Order) {
3 self.orders.append(order)
4 }
5
6 func getOrders() -> Array<Order> {
7 return self.orders
8 }
在Order类关联Customer时,建立Customer到Order的关联。也就是将当前订单添加进该用户对应的订单数组中,具体做法如下:
与之对应的规则是Change Bidirectional Association to Unidirectional(将双向关联改为单向关联),就是根据特定需求删去一个链。就是说,原来需要双向链,可如今由于需求变更单向关联即可,那么你就应该将双向关联改为单向关联。
八、Replace Magic Number with Synbolic Constant(以字面常量取代魔法数)
这一点说白了就是不要在你的应用程序中直接出现字数值。这一点很好理解,在使用字面数值时,我们要使用定义好的常量来定义。因为这样更易于维护,如果同一个字面数值写的到处都是,维护起来及其困难。当使用字面常量时维护起来就容易许多。该规则比较容易理解,在此不做过多的赘述。看下方实例即可。对于下方的实例而言,如果在版本迭代中所需的PI的精度有所改变,那么对于替换后的程序而言,我们只需修改这个常量的值即可。
1 func test(height: Double) -> Double {
2 return 3.141592654 * height
3 }
4
5 //替换
6 let PI = 3.141592654
7 func test1(height: Double) -> Double {
8 return PI * height
9 }
九、Encapsulate Field(封装字段)
当你的类中有对外开放字段时,最好将其进行封装,不要直接使用对象来访问该字段,该优缺点与上述的“自封装字段”的优缺点类似。因为直接访问类的字段,会降低程序的模块化,不利于程序的扩充和功能的添加。再者封装是面向对象