2017年4月30日 星期日

替死鬼模式

cxxlObject 物件須所有持有者放棄才會結束,若有特殊的持有者不會主動放棄,而是要等其他所有持有者放棄之後才會跟者放棄。

這時就有難題了,要怎麼知道其他持有者都放棄了,這時替死鬼就派上用場了,特殊的持有者仍持有該物件,其他持有者則改持有替身,等所有持有者放棄替身後,再由替身去要求特殊的持有者放棄該物件。


以下範例做到類似 Singleton 模式 的功能,差別只在物件無持有者時仍會被解構

#include <iostream>
#include <SMART_PTR.HPP>
#include <UTF8STRING.HPP>
#include <CXXLAVLTREE.HPP>

using namespace std;
using namespace CxxlMan2;

// Base
class A:virtual public cxxlObject
{
protected:
  // 物件容器,新建構的物件保存一份
  static cxxlAVL_Tree<A, UTF8_String, true> A_Tree;
};

cxxlAVL_Tree<A, UTF8_String, true> A::A_Tree;

class A1:public A
{
  // Constructor
  A1()
  {
    // 替身同時產生
    pSbstituteu = new Sbstituteu_t(this);    
    cout << "A1 Constructor" << endl;
  }
public: // Destructor virtual ~A1() { cout << "A1 Destructor" << endl; } void f() { cout << "A1::f()" << endl; } // 替死鬼 class Sbstituteu_t :public cxxlObject { Smart_Ptr<A1> A1_Ptr; // 主角,為它做替身 public: Sbstituteu_t(A1 *a) :A1_Ptr(a) { } virtual ~Sbstituteu_t() { // 替身結束,也要刪除主角 A::A_Tree.Delete("A1"); } A1 *operator->() const { return A1_Ptr; } }*pSbstituteu; // 用來取得替身 static Smart_Ptr<Sbstituteu_t> Create() { // 先在容器中找看看 Smart_Ptr<A> A_Ptr = A_Tree.GetObj("A1"); if (A_Ptr.isNULL()) // 若物件還未建立 { A_Ptr = new A1; A::A_Tree.Add(A_Ptr, "A1"); } // 不傳回物件,而傳回替身 return (Smart_Cast<A1>(A_Ptr))->pSbstituteu; } }; // 每種物件都應有其對應的替死鬼 class A2 :public A {
  // Constructor
  A2()
  {
    pSbstituteu = new Sbstituteu_t(this);
    cout << "A2 Constructor" << endl;
  }
public: // Destructor virtual ~A2() { cout << "A2 Destructor" << endl; } void f() { cout << "A2::f()" << endl; } class Sbstituteu_t :public cxxlObject { Smart_Ptr<A2> A2_Ptr; public: Sbstituteu_t(A2 *a) :A2_Ptr(a) { } virtual ~Sbstituteu_t() { A::A_Tree.Delete("A2"); } A2 *operator->() const { return A2_Ptr; } }*pSbstituteu; static Smart_Ptr<Sbstituteu_t> Create() { Smart_Ptr<A> A_Ptr = A_Tree.GetObj("A2"); if (A_Ptr.isNULL()) { A_Ptr = new A2; A::A_Tree.Add(A_Ptr, "A2"); } return (Smart_Cast<A2>(A_Ptr))->pSbstituteu; } }; int main() { { Smart_Ptr<A1::Sbstituteu_t> v1_Ptr = A1::Create(); (*v1_Ptr)->f(); Smart_Ptr<A1::Sbstituteu_t> v2_Ptr = A1::Create(); (*v1_Ptr)->f(); } cin.get(); return 0; }
執行結果:


可以看出 A1 只被建立一次,兩次 A1::Create() 所取得的都是同一份物件,無持有者時也能順利被解構





沒有留言:

張貼留言