淺談程式設計思想
一、鏈式程式設計
OC中有一個使用非常廣泛的框架——masonry。在masonry中,我們可以使用“點語法”實現方法呼叫。但是OC 的呼叫方法使用“[Class func]”。相比於OC中反人類的AutoLayout語法,masonry的鏈式語法使用的便利性,被廣大iOS開發者所接受。
masonry語法:↓
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(superview.mas_top).with.offset(10);
make.left.equalTo(10);
make.bottom.right.equalTo(-10);
}];
上面的示例程式碼中,鏈式程式設計思想被體現,並且極大的簡化了自動佈局程式碼。
今天我們由簡到繁,逐步實現這樣的鏈式語法設計。
首先建立一個Person類檔案,該類檔案在下面的示例中均被使用。
#import <Foundation/Foundation.h>
@interface Person : NSObject
@end
我們最終想要實現的方法呼叫格式為:
self.p = [[Person alloc] init];
self.p.eat(2);
1.block定義為屬性
block定義為屬性時,常備用於反向傳值(此處不再討論)。現在我們僅僅給出屬性定義語法!
#import <Foundation/Foundation.h>
@interface Person : NSObject
/* block型別屬性:(ARC使用strong,非ARC使用copy) **/
@property (nonatomic, strong) void(^eat)();
@end
2.block作為方法引數使用
block作為程式碼引數使用,可以向方法傳遞一個可被執行的程式碼塊。這也是很多框架中常用的一種設計方式。例如常用的AFN框架中,對網路請求結果的處理。相比於用協議實現回撥功能,這樣寫可以使程式碼更加緊湊!
例如我們在Person中定義一個eat(吃)的方法:
#import <Foundation/Foundation.h>
@interface Person : NSObject
/** block當引數(block程式碼塊)*/
- (void)eat:(void (^)())block;
@end
此時作為Person的呼叫者,我們可以將 eat 的具體行為通過程式碼塊的形式傳遞給該方法執行:
/** block當做方法的引數使用 */
- (void)demo2 {
self.p = [[Person alloc] init];
[self.p eat:^{
NSLog(@"我是怎樣吃飯的");
}];
}
到此並沒有結束,我們還需要在Person檔案中將宣告的該方法實現。並呼叫執行引數block。否則我們的block程式碼塊沒有被呼叫當然不會被執行:
#import "Person.h"
@implementation Person
// 實現宣告方法並呼叫block
- (void)eat:(void (^)())block {
block();
}
@end
然後用例項呼叫該 eat 方法,我們會在控制檯看到結果:
3.block作為方法返回值
本文開頭提到,使用“點語法”呼叫方法。既然block作為引數使用很廣泛,那我們是不是可以用它作為返回值使用?答案是肯定的!
我們看masonry的方法:在bolck內點開 make.top.equalTo 方法,我們看它的返回值:
我們看到它的返回值是一個block型別,MASConstraint是返回值型別,我們暫且先不管(以 void 型別替換)。到此我們可以有一點想法了。
我們模仿masonry的該方法定義我們的自己Person類的 eat 方法:
#import <Foundation/Foundation.h>
@interface Person : NSObject
/** block作為方法返回值使用 */
- (void(^)(int))eat;
@end
宣告瞭該方法,當然還要實現它:
#import "Person.h"
@implementation Person
- (void (^)(int))eat {
return ^(int n){
NSLog(@"吃了 %d 個饅頭!!!", n);
};
}
@end
到這我們貌似搞定了,接下來試試到底行不行:
- (void)demo3 {
// block當返回值
self.p = [[Person alloc] init];
self.p.eat(2);
}
執行,控制檯列印出來了我們期待的結果:
寫到這裡,我們已經搞清楚了鏈式語法結構的實現原理。我們寫了一個很簡單的小栗子循序漸進,貌似很簡單有沒有。
4.鏈式語法結構的實現
但是我們知道masonry中我們可以用點語法連續呼叫,比如:make.bottom.right.equalTo(-10); 可以連續的用點語法呼叫。我們不妨設計一個簡單的demo ,使其實現類似masonry的語法。具體如何實現,可以學習masonry的設計。(最終我們想要的結果是可以連續呼叫的語法結構 add(value).add(value).add(value) )
開啟masonry的約束方法:
mas_makeConstraints 方法被設計在 UIView的分類中,分析我們要實現的demo的需求,應該將計算方法宣告在NSObject的分類中!引數 MASConstraintMaker 為方法呼叫者,藉此分析我們建立NSObject的分類以及計算管理者Manager,並宣告計算方法:
#import <Foundation/Foundation.h>
#import "Manager.h"
@interface NSObject (Tools)
/** 計算方法 */
+ (int)KY_makeCalculate:(void(^)(Manager *mgr))block;
@end
引數Manager就是我們的計算方法管理者,我們在該類中宣告加法運算,並根據之前點語法的實現原理,以block作為返回值:
#import <Foundation/Foundation.h>
@interface Manager : NSObject
- /** 加法計算 */
- (void(^)(int))add;
@end
接下來我們貌似就可以呼叫了:
- (void)demo4 {
// 鏈式實現
int result = [NSObject KY_makeSum:^(Manager *mgr) {
mgr.add(5);
}];
NSLog(@"運算結果----> %d", result);
}
但是,對於連續的 add(value) 方法呼叫,貌似我們並沒有實現!其實只要將返回值void型別改為管理者本身就可以了,另外我們再宣告一個屬性將計算結果臨時儲存一下:
#import <Foundation/Foundation.h>
@interface Manager : NSObject
/** 計算結果 */
@property (nonatomic, assign) int result;
- (Manager *(^)(int))add;
@end
.m 檔案中實現我們的 add 方法:
#import "Manager.h"
@implementation Manager
- (Manager *(^)(int))add {
return ^(int value) {
_result += value;
return self;
};
}
@end
接下來我們再呼叫一下:
// 鏈式實現
- (void)demo4 {
// 鏈式實現
int result = [NSObject KY_makeSum:^(Manager *mgr) {
mgr.add(1).add(2).add(3).add(4).add(5);
}];
NSLog(@"運算結果----> %d", result);
}
然後我們執行測試,看下結果:
真的可以了,哈哈哈哈哈????!!!!
Swift 本身就是鏈式的語法結構,所以寫起來就相對簡單的多了,在此不再過多的複數了。
二、響應式程式設計
響應式程式設計概念性的定義,很難懂!找到的定義是:響應式程式設計是一種面向資料流和變化傳播的程式設計正規化。這意味著可以在程式語言中很方便地表達靜態或動態的資料流,而相關的計算模型會自動將變化的值通過資料流進行傳播。
僅僅看定義的話真的很難理解,在網上找到一個感覺可以加深一下理解。例如,在指令式程式設計環境中,a=b+c表示將表示式的結果賦給a,而之後改變b或c的值不會影響a。但在響應式程式設計中,a的值會隨著b或c的更新而更新。
響應式程式設計, 開發中我們常見和常用的 Target、Delegate、KVO、通知、時鐘、網路非同步回撥等,都屬於響應式程式設計。(有事件觸發時響應相關事件)。這些我們使用過的方法或許可以幫助我們理解其概念。
OC中有一個響應式程式設計框架 ReactiveCocoa(RAC)
其它的資料暫時還未找到。。。~~~~(>_<)~~~~
三、面向協議程式設計
我們常聽到的應該是OOP的概念,即物件導向的程式設計。OOP的核心思想是使用封裝和繼承,將一系列相關的東西放到一起。舉個小例子幫助理解一下,看一段小程式碼:
/// 動物類
class Animal {
- func eat() {
print("吃東西")
}
func run() {
print(" 2 條腿跑")
}
}
/// 繼承自動物類的人
class Dog: Animal {
- override func run() {
print(" 4 條腿跑")
}
func bite() {
print("咬人")
}
}
let dog = Dog()
person.eat()
person.run()
我們定義了一個動物類Animal,然後抽象出它的leg(腿)屬性,以及eat(吃)、run(跑)的方法。子類Dog繼承Animal,並根據自己的特性重寫了run(跑)的方法。而對於eat(吃)已經滿足需求,不必重寫。
Dog和Animal共享了一部分程式碼eat(吃),這部分程式碼被封裝在父類中,所有繼承自Animal的子類都可以使用。這也就是我們剛才提到的OOP的核心思想——使用封裝和繼承,將一系列相關的東西放到一起。
再看,Dog類中我們還寫了一個方法bite(咬人),狗會咬人。然後我們還要寫一個類Wolf(狼)繼承Animal(動物),同樣狼也會咬人。
/// 繼承自動物類的人
class Wolf: Animal {
- override func run() {
print("四條腿跑")
}
func bite() {
print("咬人")
}
}
但是我們不得不重新寫bite方法,因為我們無法使用Dog(狗)的bite方法。這時就會看到程式碼的重複性。同樣,我們要在Dog(狗)中新增bark(叫)方法,而狼也會叫,此時就需要在Wolf中再次新增bark(叫)方法。如此下來,程式碼會顯得越來越臃腫,並且擴充套件性和維護性會大大降低。而OC和Swift程式碼中不能夠多繼承!
此時我們就用到了協議的另一個功能,定義統一的方法bark(叫),然後由Dog和Wolf分別遵守該協議:
protocol BarkProtocol {
func bark()
}
這樣我們就在協議中統一規定了Dog和Wolf共有的Bark(叫)方法,但是這樣貌似也需要在子類中分別實現該方法,但是,這樣寫的好處無疑會比之前的方法好很多。至少它可以在需要的是否對定義的方法進行統一的修改,規範性提高不少。同樣我們還可以這樣給協議介面一個預設實現,這樣就不用在子類中去分別實現了!
import UIKit
protocol BarkProtocol {
func bark()
}
extension BarkProtocol {
func bark() {
print("狼和狗的叫聲")
}
}
以上所述是一種面向協議的程式設計思想。通過面向協議的思想,我們的實現程式碼得到優化。
-
協議定義
-
提供實現的入口
-
遵循協議的型別需要對其進行實現
-
-
協議擴充套件
-
為入口提供預設實現
-
根據入口提供額外實現
-
之前寫過的隔離地圖的設計Demo也是一種面向協議的程式設計思想。
我們的小demo描述的都很簡單,但在實際開發中,我們遇到的問題會比這複雜的多。這就需要對實際問題的具體分析,然後將這樣的程式設計思想應用其中,提高我們的程式碼質量!開發中要培養良好的程式碼習慣,將這些我們看似簡單的東西應用到專案開發中。不要一味地為了實現功能而寫程式碼,更多的融入一些設計思想,會使我們的程式碼更舒適!
相關文章
- 淺談非同步程式設計非同步程式設計
- 淺析iOS-MAS&鏈式程式設計思想iOS程式設計
- SpringBoot 非同步程式設計淺談Spring Boot非同步程式設計
- 淺談程式設計正規化程式設計
- 淺談PHP物件導向程式設計PHP物件程式設計
- 程式設計思想 面向切面程式設計程式設計
- 再談程式設計正規化—程式語言背後的思想程式設計
- 淺談程式設計師的“內卷化”程式設計師
- 【程式設計素質】程式設計思想總結程式設計
- 淺談高可用設計
- 淺談程式設計師職業生涯規劃程式設計師
- 程式設計思想之冪等性 | 程式設計之道程式設計
- JAVA語言程式設計思想Java程式設計
- 程式設計思想 物件導向程式設計物件
- 淺談函數語言程式設計與 Java Stream函數程式設計Java
- 設計模式--原型模式及其程式設計思想設計模式原型程式設計
- 程式設計中的自頂向下設計思想程式設計
- 淺談C++物理設計:設計原則C++
- MR核心程式設計思想總結程式設計
- 淺談Java、PHP、C++程式設計的優缺點JavaPHPC++程式設計
- 淺談Java中利用JCOM實現仿Excel程式設計JavaExcel程式設計
- 淺談產品模型(Profile)在程式設計中的作用模型程式設計
- 從Express到Nestjs,談談Nestjs的設計思想和使用方法ExpressJS
- 淺談VueUse設計與實現Vue
- 荒野亂鬥角色設計淺談
- 淺談設計模式——單例模式設計模式單例
- 淺談java之設計模式(1)Java設計模式
- 淺談設計模式——工廠模式設計模式
- JAVA 程式設計思想 第13章 字串Java程式設計字串
- Java 程式設計思想筆記:Learn 10Java程式設計筆記
- 淺談軟體開發中的防禦式程式設計程式設計
- 淺談業務中臺前端設計前端
- 淺談設計模式及python實現設計模式Python
- 淺談DDD(領域驅動設計)
- 淺談 DDD 領域驅動設計
- 淺談前端響應式設計(一)前端
- 淺談前端響應式設計(二)前端
- 淺談23種設計模式之單例設計模式設計模式單例
- 淺談物件導向中的一些主要思想物件