程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [OOD-More C++ Idioms] 律師與委托人 (Attorney-Client)

[OOD-More C++ Idioms] 律師與委托人 (Attorney-Client)

編輯:C++入門知識

[OOD-More C++ Idioms] 律師與委托人 (Attorney-Client)


律師與委托人 (Attorney-Client)

目的

控制訪問類實現細節的粒度。

動機

C++中的friend會開始類內部的所有細節,也因此破壞了封裝性。C++沒有提供可以選擇性使用某一部分私有成員的方式,要麼全部開放,要麼全部拒絕。例如下面例子中的類Foo聲明Bar為其友元,可以訪問它的所有私有成員。這樣增加了耦合性,類Bar也無法單獨發布,這樣並不太合適。

class Foo
{
private:
  void A(int a);
  void B(float b);
  void C(double c);
  friend class Bar;
};

class Bar {
// 這個類只需要使用Foo::A和Foo::B.
// 但它其實可以訪問Foo所有的成員.
};

如果能選擇確定需要使用到的一組成員,而不是全部,就可以降低耦合性。而這個律師與委托人的慣用法就可以精准的控制友元所能使用的成員。

解決方案及示例

基本思路是增加一個中間層進行控制。一個客戶類可以指定一個律師(Attorney)類作為其友元類,再由此律師類擔當其它類使用客戶類的代理。與典型的代理(proxy)類不同的是,律師類會限制一個可以使用的成員子集。比如上面的例子中,將Foo改為Client, 再提供一個中間類限制只允許訪問Client::A和Client::B。代碼如下:

class Client
{
private:
  void A(int a);
  void B(float b);
  void C(double c);
  friend class Attorney;  // 這裡指定友元類
};

class Attorney {
private:
  static void callA(Client & c, int a) {
    c.A(a);
  }
  static void callB(Client & c, float b) {
    c.B(b);
  }
  friend class Bar;
};

class Bar {
// 現在Bar通過Attorney類就只能使用Client::A和Client::B了。
};

類圖如下:

general

AttZ喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcm5lecDg1rvT0Mu909C1xGlubGluZSBzdGF0aWO6r8r9o6zDv7j2tryz1tPQ0ru49kNsaWVudMq1wP21xNL908OjrNTZ16q2+LX308O6z8rKtcS3vbeooaO99rGjs9bLvdPQyrXP1qOsv8nS1LHcw+Kxu8bky/zA4Mq508Oho8v509DQ6NKqyrnTw0NsaWVudLa80qrU2kF0dG9ybmV51tDJ+cP3zqrT0dSqwOCho8jnufvDu9PQQXR0b3JuZXnA4KOsvs3Q6NKq1rG909DeuMRDbGllbnTA4KGjPC9wPg0KPHA+we3N4ru5v8nS1Mq508O24Lj2wsnKpihBdHRvcm5leSnA4LfWwOuz9rbUsrvNrMu909DKtc/WtcS3w87KoaM8L3A+DQo8cD67udPQ0ru49tPQyKS1xLC4wP3Kx8zhuanSu7j2wsnKpihBdHRvcm5leSnA4Nf3zqq24Lj2wOC1xNbQvOTIyyhtZWRpYXRvcimjrMC0zbPSu8zhuam21Mv8w8fLvdPQyrXP1rXEt8POyqGj1eK49snovMa/ydLU08PT2r3ivvZDKyvW0M7et6i8zLPQ09HUqsDgy/m0+MC0tcTOyszio6zS8s6qy73T0Mq1z9a1xNDpuq/K/crHv8nS1LG7u/nA4LX308O1xKGjIM/Cw+bV4rj2wP3X08Dvo6xEZXJpdmVkOjpGdW5jysfSu7j2tuDMrMq1z9aho82ouf3V4rj2ud/Tw7eozazR+b/J0tTKudPDtb1EZXJpdmVk1tC1xMu909DKtc/WoaM8L3A+DQo8cHJlIGNsYXNzPQ=="brush:java;"> #include class Base { private: virtual void Func(int x) = 0; friend class Attorney; public: virtual ~Base() {} }; class Derived : public Base { private: virtual void Func(int x) { printf(Derived::Func ); // 雖然沒有繼承基類中的友元關系,但仍然可以被訪問。 } public: ~Derived() {} }; class Attorney { private: static void callFunc(Base & b, int x) { return b.Func(x); } friend int main (void); }; int main(void) { Derived d; Attorney::callFunc(d, 10); }

類圖如下:

special

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved