亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

對象設(shè)計(jì)要考慮有效范圍

hatlonely / 2565人閱讀

摘要:另載于現(xiàn)代對象設(shè)計(jì)主張組合優(yōu)于繼承。對象的有效范圍,是指對象從創(chuàng)建到丟棄不再引用的這段時(shí)間,不包括等待被銷毀的時(shí)間。對于繼承也是同理,父類和子類應(yīng)當(dāng)有相同的有效范圍。同理,級的對象不要持有級的對象。

另載于 http://www.qingjingjie.com/blogs/9

現(xiàn)代對象設(shè)計(jì)主張“組合優(yōu)于繼承”??傊疅o論組合還是繼承,對象都成了涉及多個(gè)類的復(fù)合結(jié)構(gòu)。

“對象的有效范圍”,是指對象從創(chuàng)建到丟棄(不再引用)的這段時(shí)間,不包括等待被GC銷毀的時(shí)間??梢越普J(rèn)為是對象的生命期。

單例對象(Singleton)的有效范圍幾乎是整個(gè)應(yīng)用的開啟時(shí)間,Socket的有效范圍通常是網(wǎng)絡(luò)連接的持續(xù)時(shí)間,而一個(gè)臨時(shí)的Integer則可能瞬間就被丟棄了。Let"s 注意,不同范圍的對象/類,不能隨意地組合/繼承在一起。

1. 不同范圍的對象避免打包在一起

(代碼有點(diǎn)多,如果嫌煩可以跳過1.先看2.)

反面教材:我們來看一個(gè)客戶端程序,它通過socket與某個(gè)服務(wù)器保持通信,不斷發(fā)消息并收取響應(yīng)。

public class Communication {
  private Topic topic;
  private Socket socket;

  public Communication(String host, int port) {
    socket = new Socket(host, port);
  }
  public void close() {
    socket.close();
  }
  public void setTopic(Topic topic) {
    this.topic = topic;
  }
  public String sendReceive(String msg) {
    return sendRecv_(topic, msg);
  }
  private String sendRecv_(Topic topic, String msg) {
    ... // 具體處理
  }
}

我們有兩個(gè)主題(topic) A和B,以不同主題發(fā)的消息,服務(wù)器會做不同處理。我們一會兒用主題A發(fā)消息,一會用主題B發(fā)消息。代碼如下:

Communication comm = new Communication(host, port);
comm.setTopic(A);
comm.sendReceive("Hello!");
comm.sendReceive("How are you?");

comm.setTopic(B);
comm.sendReceive("Good morning!");
comm.sendReceive("Let"s begin");

comm.sendTopic(A);
comm.sendReceive("How old are you?");

切換來切換去,真麻煩。如果你不嫌麻煩,假設(shè)給Communication再加一個(gè)域"config",平均每發(fā)100條消息,要切換一次config,平均每發(fā)10條消息,要切換一次topic,還是交替進(jìn)行,煩不煩!

再想想,如果多個(gè)線程在使用comm對象呢? 呵呵呵,完蛋了。

Communication的有效范圍與socket一致,而topic的有效范圍就小于socket了,因此topic就不該放在這個(gè)類里。雖然sendReceive()可以少填一個(gè)參數(shù),看似方便,但是引發(fā)了更多麻煩。
對于繼承也是同理,父類和子類應(yīng)當(dāng)有相同的有效范圍。

所以還是這么寫吧:

comm.sendReceive(A, "Hello!");
comm.sendReceive(A, "How are you?");
comm.sendReceive(B, "Good morning!");

稍微有點(diǎn)麻煩呢

或者這么寫:

class CommByTopic {
  private Communication comm;
  private Topic topic;
  // 構(gòu)造函數(shù)省略
  public String sendReceive(String msg) {
    return comm.sendReceive(topic, msg);
  }
}

CommByTopic onA = new CommByTopic(comm, A);
onA.sendReceive(msg);
onB.sendReceive(msg);

缺點(diǎn)是comm關(guān)閉后要注意不能繼續(xù)使用onA。所以不要長時(shí)間持有onA對象,最好能局限在方法作用域內(nèi)。

或者試試簡潔的lamda~

Lamda in Java 8:

Function onA = msg -> comm.sendReceive(A, msg);
onA.apply("Hello!");
onA.apply("How are you?");

Lamda in Scala:

val onA: String => String = comm.sendReceive(A, _)
onA("Hello!")
onA("How are you?")

// 柯里化的寫法 val onA = comm.sendReceive(A) _
2. 大范圍對象不要持有小范圍對象

上面說的comm就是大范圍對象,socket也是大范圍對象,topic是小范圍對象。它們生命長短不同。

如果大范圍對象持有了小范圍對象,你就要疲于切換,甚至擔(dān)心線程安全性。反過來,小范圍對象持有大范圍對象,就好了。當(dāng)然了,持有相同范圍的對象也是好的。

對運(yùn)行于IoC容器的程序尤其明顯。來溜一段基于Spring MVC的應(yīng)用代碼:

@Component
@Scope("singleton") //單例對象
public class Manager {
  @Autowired
  private Account account;

  public void freezeAccount() {
    account.freeze();
    merge(account);
  }
}

@Component
@Scope("request") //request范圍的對象
public class Account {
  ...
}

這樣的代碼在系統(tǒng)啟動時(shí)就崩了,因?yàn)閍ccount還沒出現(xiàn)。就算你給Manager標(biāo)上@Lazy (延遲初始化),讓它在賬戶A發(fā)來請求時(shí)才初始化,它也只能正確處理這次的請求。下次賬戶B再來請求時(shí),它還是使用上次的A的account來操作,而不會用B的account。呵呵呵,完蛋了。
同理,session級的對象不要持有request級的對象。

對于Servlet和Filter也是如此,它們是近似于單例的對象,讓它們持有一些配置數(shù)據(jù)和常量就行了,如果讓它們持有當(dāng)前的userId,也很危險(xiǎn)。

再提醒一下,其實(shí)小范圍對象持有大范圍對象也不要濫用,一不小心就會讓對象承擔(dān)過多職責(zé),有過多依賴。設(shè)計(jì)要從職責(zé)出發(fā)。

結(jié)語

之所以要從“有效范圍”的角度談對象設(shè)計(jì)的問題,就是想給大家提供一個(gè)明確可操作的分析視角,這可比“設(shè)計(jì)哲學(xué)”容易多了。

不過光會這個(gè)還不夠,知識要全面。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/64139.html

相關(guān)文章

  • 如何有效地同多個(gè)云提供商合作

    摘要:在同多個(gè)云提供商合作之前,請?jiān)u估他們在計(jì)算存儲和安全等方面的服務(wù)。企業(yè)必須在多個(gè)云供應(yīng)商中做出抉擇。在與多個(gè)云供應(yīng)商合作時(shí)有一些策略和技巧,能夠得到其優(yōu)點(diǎn)同時(shí)限制了重復(fù)勞動和其他額外的工作。 在同多個(gè)云提供商合作之前,請?jiān)u估他們在計(jì)算、存儲和安全等方面的服務(wù)。企業(yè)必須在多個(gè)云供應(yīng)商中做出抉擇。亞馬遜網(wǎng)絡(luò)服務(wù)是行業(yè)巨頭,而微軟Azure則提供了一整套越來越有競爭力的服務(wù)。還有谷歌云平臺對于那些...

    xavier 評論0 收藏0
  • 軟件測試剛?cè)胄斜乜矗?測試基本流程、測試用例全在這里

    摘要:從業(yè)務(wù)流程上,應(yīng)得到以下信息主流程是什么條件備選流程是什么數(shù)據(jù)流向是什么關(guān)鍵的判斷條件是什么測試用例設(shè)計(jì)完成以上兩步則可進(jìn)行測試用例設(shè)計(jì),功能測試用例,應(yīng)盡量考慮邊界異常性能的情況,以便發(fā)現(xiàn)更多的隱藏問題。 為什么測試人員要參加需求分析?也就是進(jìn)行測試需求分析的目的是什么? 第一、把用戶需求...

    Cristalven 評論0 收藏0
  • 軟件測試肖sir__005測試用例設(shè)計(jì)方法(1)

    摘要:需要結(jié)合其他測試用例設(shè)計(jì)的方法進(jìn)行補(bǔ)充。比如邊界值邊界值在軟件中邊界值測試方法是發(fā)現(xiàn)錯誤能力最強(qiáng)的一種。其中,原因是表示輸入條件,結(jié)果是對輸入執(zhí)行的一系列計(jì)算后得到的輸出。與取值或,表示某狀態(tài)不出現(xiàn),則表示某狀態(tài)出現(xiàn)。 ...

    gnehc 評論0 收藏0
  • 2017前端性能優(yōu)化清單

    摘要:性能最好具有可量化可監(jiān)測以及可改動的特性。下文是一份年的前端性能優(yōu)化清單,闡述了作為前端開發(fā)人員,為了確保反饋速度以及瀏覽器兼容性我們需要考慮的問題。地圖設(shè)計(jì)的決定違背了性能理念,所以他在這份清單內(nèi)的順序有待考慮。 2017前端性能優(yōu)化清單 你開始使用漸進(jìn)啟動了么?是不是已經(jīng)使用過React和Angular中tree-shaking和code-splitting兩個(gè)工具?有沒有用過Br...

    verano 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<