在上一篇介紹了邏輯編程的做用,介紹了邏輯編程中的一些概念,包括邏輯程序的結構:事實、規則和問題;知識的表達方式:謂詞演算、產生式規則,以及這些概念與三維度(角色+場景+時間)理論的契合關係,正式提出了「三維度邏輯編程」這個概念。爲了更好的體現「三維度」的關係,今天要重點介紹一下角色的扮演者--Actor。html
這個標題來自電影《喜劇之王》周星馳的臺詞。人生如戲全靠演技,星爺這樣說,咱們又未嘗不是呢?編程
(圖片來自網絡,侵刪)安全
在咱們的「遊戲人生」這個遊戲中,三好男人張三在家是丈夫,有了孩子後是父親,他在老婆面前必須當好丈夫角色,在孩子面前必須當好父親角色,一樣張三在單位工做的時候必須當好員工角色,爲了賺錢養家,老闆要求996也得忍。。。加班回家一身疲憊,也得面帶微笑,當好丈夫或者父親角色。只有在夜深人靜的時候,張三才能作回張三本身。張三一天深夜在某個聊天羣寫下了一段話:網絡
夜深了, 我尚未睡, 想着寫了2年半的代碼, 是一種情懷, 能堅持到最後的勇氣, 像極了18歲的本身。 我很菜,卻依然堅持, 羣裏全是我膜拜的大神, 談的我全不懂, 我依然願意在羣裏, 發點感慨 明天繼續! -----致和我同樣努力寫bug的垃圾碼農
Actor,顧名思義:演員。在咱們的「三維度」邏輯程序中,使用Actor這個詞來表示扮演角色的原生對象。Actor對象須要扮演多種角色,在不一樣的地點(好比在家,在公司)、不一樣的時期扮演不一樣的角色。Actor是「社會化意義」上的人,好比行駛一我的或一羣人的意志的團體,或者機構、公司,或者一部機器。若是Actor是一我的,就必定會扮演一個角色,一輩子要扮演不少角色,因此,Actor與角色的關係就像人和影子同樣,只要在陽光下老是如影隨行。架構
在當前這個「遊戲人生」程序中,下面的示例代碼描述了張三和貂蟬兩個Actor對象具備的一些角色:張三是一個員工,張三同時也是貂蟬的丈夫;貂蟬是張三的妻子。框架
//建立實體Actor對象 Woman diaochan = new Woman() { Name = "貂蟬", Birthday = new DateTime(1990, 1, 2) }; Man zhangsan = new Man() { Name = "張三", Birthday = new DateTime(1988, 3, 5) }; //陳述事實:XX是YY角色 Worker worker1 = new Worker(zhangsan); Wife wife1 = new Wife(diaochan,zhangsan); Husband husband1 = new Husband(zhangsan,diaochan);
注意上面的代碼只是在申明Actor對象的實例,陳述Actor對象具備的角色事實關係。這裏藉助C#對象的構造函數,來爲Actor對象申明一個相關的角色,這個角色會添加到Actor對象的角色集裏面。可是爲何要用角色對象的構造函數而不是Actor對象的角色集合添加角色對象呢?好比下面這樣子的代碼:編程語言
zhangsan.Roles.Add(new Worker); zhangsan.Roles.Add(new Husband(diaochan));
上面的代碼的確能夠實現Actor Has a Role的效果,可是有幾個問題:函數
1,上述代碼沒有以前的代碼簡潔;spa
2,以Actor對象爲主,角色對象是Actor對象的附屬對象.net
3,描述多個Actor對象之間的關係不方便,語義不清晰。
4,沒法體現出邏輯編程中的謂詞關係。
因此,要解決這些問題,或者說要弄清楚「三維度」邏輯編程的特色,須要深入的認識角色的含義,角色與Actor真正的從屬關係。
謂詞(參考定義)是用來刻畫個體性質以及個體之間相互關係的詞。在當前程序中,角色對象定義了對象的性質,也能夠定義對象之間的關係,所以這裏的角色就是一個謂詞,Actor對象就是謂詞對象的參數,一個謂詞也能夠表示多個Actor對象參數之間的關係。因此Worker、Wife、Husband都是謂詞,是表達Woman/Man稱謂的詞。在邏輯編程中,強調對象之間的邏輯關係,這種關係就是謂詞關係,邏輯編程就是謂詞演算。爲了更好的將邏輯編程與「三維度」(角色+場景+時間)理論聯繫起來,在「三維度」邏輯編程中將謂詞稱爲角色謂詞,程序的運行依賴於角色在系統中的交互。那麼角色是什麼,爲何這麼重要呢?
人的社會性表如今人和人之間各類關係的總和,這些關係造成一個複雜的網絡,角色是其中的一種關係。這種關係有時候是不穩定的,有時候是穩定的。例如:
經過這些角色關係,咱們的社會有機的組織了起來,有條不紊的運行着。總之,角色表達的是一個主體對象跟一個或者多個從屬對象的關係,若是角色關係是不穩定的,從屬對象能夠不明確指出,當它仍然存在。
天下人無非追求的就是名利,要想作事就必須有一個名頭,大到行軍打仗須要「出師有名」,小到送個外賣,沒有一個合適的工做角色就無法正大光明的去作事情,能作某件事情的名頭就是角色,這個名頭表明一種身份、社會地位以及權利。科學的解釋是角色即爲」必定社會身份所要求的通常行爲方式及其內在的態度和價值觀基礎「。總而言之,一我的必須以某種角色去作某些事情,在作事情的時候扮演一種角色。爲了明確區分不一樣的角色,須要給每種角色一個約定俗成的名字,一個稱謂,這即是角色謂詞。
在「三維度」邏輯編程中,每個角色都是一個惟一的角色類,它們都繼承自一個角色接口,該接口定義了角色名字和角色的擁有者,在定義具體角色的時候必須確保名字的惟一性和名字的約定俗成。
interface IRole<out T> where T : Actor { string RoleName { get; } T Owner { get; } bool MatchRules(string ruleName); }
上面接口的定義反映出一個接口一定有一個它的擁有者,這個擁有者一定是一個Actor對象。這裏角色擁有者做爲角色對象的一個屬性出現,也體現出來了角色和角色擁有者之間的主從關係。
前面說了角色的重要性,人必需要扮演一種角色去作某件事情,這是人的社會性的必然。人類社會就是由一套複雜的角色驅動着。這套角色,中國儒家稱之爲「禮」,君臣有禮,三綱五常,經過這套體系維持封建社會的穩定運轉。現代國家更是設置了嚴密的等級體系,每一個二年都在這個體系裏面生活、工做,好比體制內外的人社會地位有明顯的差異,咱們每一個人都想去當公務員,都想當大老闆。正是這些理想的社會角色,讓咱們每一個人爲之期盼、奮鬥,永不停留腳步,有人叫你一聲因此XX總,YY局,是否是很愜意?因此,你叫別人是什麼不重要,別人叫你是什麼才重要,角色纔是咱們每一個人真正的主人。
這段話代表在描述角色和Actor之間的關係的時候,應該以角色爲主,Actor爲輔助,因此在咱們的邏輯編程中使用角色爲謂詞,稱爲角色謂詞,以Actor對象爲角色謂詞的參數,使用C#來表達,就是前面已經說過的樣子:
Worker worker1 = new Worker(zhangsan); Wife wife1 = new Wife(diaochan,zhangsan); Husband husband1 = new Husband(zhangsan,diaochan);
經過使用角色對象的構造函數,更容易將目光關注到對象的構造申明上,而不是構造的過程。咱們忽略無關的細節,更容易重視代碼表達的語義,體現出了角色對象和Actor對象之間的從屬關係。
雖說角色對於劇本講故事很重要,可是再怎麼重要的角色也須要一個出色的演員。演員的演技是可否駕馭角色的關鍵,下面須要咱們再來介紹下這位演員了。
沒有Actor,角色將毫無心義,做爲演員,它爲角色而生。因此Actor對象須要內置一個角色集合,且不可移除,不可重置,只能向角色集合添加或者移除某個角色。每個Actor對象最終都繼承自一個Actor抽象類,它有誕生時間,也有名字。此文,它還有扮演某個角色的方法,這讓Actor天生有了當演員的才能。
abstract class Actor { public Actor() { Roles = new List<IRole<Actor>>(); AtTime = DateTime.Now; } protected internal List<IRole<Actor>> Roles { get; private set; } public T ActAs<T>() where T : class,IRole<Actor> { foreach (IRole<Actor> role in Roles) { if (role is T) return role as T; } throw new InvalidCastException("Actor沒有此角色:" + typeof(T).Name); } public DateTime AtTime { get; set; } public string Name { get; set; } }
上面Actor抽象類的設計,讓Actor具備了扮演角色的能力。咱們知道扮演角色是爲了可以執行角色定義的方法,因爲Actor的角色並非穩定的,角色在須要的時候纔有,也會在特定的時候失去,因此在設計上Actor不能繼承角色接口,也不該該將接口的方法直接定義在Actor對象中。那麼可否讓Actor對象直接執行角色對象的方法呢?也就是讓對象動態添加一個方法/函數,這個功能在動態類型語言不是什麼問題(好比Javascript、Python、Lisp等),但對於靜態類型語言倒是很是困難的問題(好比C++、Java、C#、go等)。
下面演示的是Javascript動態添加屬性和方法的例子:
var object = new Object(); object.name = "name"; object.age = 19; object.fun = function(){ console.log("這是一個動態添加的方法") } object.fun();//調用新增的方法
然而,採用動態類型語言這種動態添加方法的方案難以在語義上表達調用這個方法所包含的角色語義,更爲重要的是調用這種動態的方法不能保證類型安全,好比讓一個員工(角色)對象調用了老闆角色「發工資」的方法這種錯誤的事情發生。「三維度」邏輯編程提出了角色謂詞的概念,而且在設計上明確要求由Actor對象來扮演角色,經過角色對象來安全的執行角色的方法,這不只在代碼上體現了角色語義,也保證了類型安全,讓指定的角色幹指定的事情,不會越俎代庖,每一個人職責分明,系統有條不紊。
Actor經過切換角色來實現不一樣的功能,這個能夠經過Actor對象的ActAs泛型方法來切換當前Actor對象的角色。ActAs泛型方法遍歷Actor當前角色集合中全部的角色,若是找到就返回這個角色類型,找不到拋出異常,詳細代碼請看上面【演員的天分】。
回顧一下前面程序中Actor對象經過ActAs泛型方法切換當前角色執行角色功能的的示例代碼示例,因爲能夠經過Actor對象來切換到擁有的角色對象,因此申明角色對象的變量都不須要了,這樣能更加顯示出角色謂詞的強大力量:
//使用角色謂詞表示事實關係
new Worker(zhangsan);
new Wife(diaochan,zhangsan);
new Husband(zhangsan,diaochan);
//場景參與人開始扮演角色 diaochan.ActAs<Wife>().Child_bearing(); zhangsan.ActAs<Husband>().Money += zhangsan.ActAs<Worker>().Work(); zhangsan.ActAs<Husband>().Child_rearing();
上面的代碼經過Actor對象切換角色來執行角色對象纔有的方法,如故事男女主角做爲夫妻功能纔有的生孩子功能,以及男主做爲員工角色進行工做賺錢的功能。事實上也原本如此,整個過程理解起來很是天然。
好演員固然說到是飾演某個角色演的淋漓盡致、唯妙唯肖的演員,然而一個演員要飾演這樣的角色,除了自身的演技,還得遇到很是好的劇本,畢竟一樣的角色你們都有機會來當,好比我也想來演一次當老闆的角色,但你是當一個小賣部老闆仍是世界500強公司的CEO,這就要看導演給你的劇本了。演小老闆有小老闆的演法,演大公司CEO就必須有CEO的演法,這裏的區別就是劇本中設定的角色規則,好比小老闆角色設定的身價不能大於100萬,而CEO角色的身價過億,CEO能夠聘請10000名員工而小老闆只有本身一個員工。哪怕是一樣的小老闆,有的劇本是小老闆一路開掛三五年作到大公司CEO,有的劇本是小老闆當了不到一年就破產下崗了。這些劇本中決定角色命運的,就是編劇/導演給角色設定的規則。
因此,咱們的「遊戲人生」劇本要講好故事,介紹完了演員和角色,還須要重點講講角色的規則,這是下一篇文章準備講的內容,也是「三維度」邏輯編程語言的重點內容,這部份內容在《SOD框架「企業級」應用數據架構實戰》已經作了相應的介紹,手裏有這本書的朋友能夠先一睹爲快。
--------------分界線-------------------------
構思整個系列花了2年多時間,寫這篇文章寫了3天,反覆刪改,但限於本人對於編程語言知識能力的淺薄,其中謬誤確定不少,前幾篇文章的內容也被PL領域的大佬批評略多。在此感謝這些大佬的批評建議,可是與大佬的水平相比較起來大佬在天上我在地上,不在一個交集上,因此這篇文章以及整個系列被大佬批判沒法避免。只是但願大佬可以手下留情,在點擊文章【反對】以前先回帖留言詳細說明您反對的地方,謝謝支持!
若是僅反對而不回帖留言,本人只好當您爲空氣,您的舉手之勞毫無心義,一概略過。