رفتن به مطلب
جامعه‌ی برنامه‌نویسان مُدرن ایران
فرهاد شیری

الگو طراحی ISP با استفاده از اشاره گر و Forward Declaration Class

پست های پیشنهاد شده

کلاسهای وکیل :

پنهان سازی جزئیات پیاده سازی به منظور جلوگیری از دسترسی به اطلاعات خصوصی و منطق خصوصی برنامه در کلاس کار مطلوبی است.

قرار دادن یک کلاس وکیل برای کاربران کلاس به طوری که از رابط عمومی این کلاس آگاهی داشته باشند باعث می شود که بدون آنکه به کاربران کلاس اجازه دسترسی به جزئیات پیاده سازی کلاس اصلی را بدهیم این کاربران بتوانند از خدمات کلاس اصلی استفاده نمایند.

ویا تصور کنید که شما کلاس جامعی دارید که می خواهید در اختیار سایر برنامه نویسان قرار دهید، در صورتی که از این تکنیک استفاده نکنید مجبور هستید سورس کلاس را هم در اختیار برنامه نویسان قرار دهید. 

در صورتی که با استفاده از این تکنیک کافی هست که شما فقط یک هدر فایل از نمای کلاس در اختیار دیگر برنامه نویسان قرار دهید و سورس کلاس را به صورت یک فایل کامپایل شده در قالب یک DLL ویا یک SO فایل در زمان اجرا به کد برنامه نویس استفاده کننده الحاق نمایید.

 به عنوان مثال ابتدا یک کلاس به نام Implementation.hتعریف می کنیم

#ifndef IMPLEMENTATION_H
#define IMPLEMENTATION_H


class Implementation
{
    public:
        Implementation() {};
        Implementation(int v) : m_Counter(v){};
        ~Implementation(){};

        unsigned int GetCounter() { return m_Counter; }
        void SetCounter(unsigned int val) { m_Counter = val; }

    protected:

    private:
        unsigned int m_Counter;
};

#endif // IMPLEMENTATION_H

همانطور که ملاحظه می کنید در کلاس فوق یک داده خصوصی تعریف کردیم با دو متد دسترسی عمومی.

و بعد یک کلاس واسط به نام Interface.h تعریف میکنیم

#ifndef INTERFACE_H
#define INTERFACE_H

class Implementation; //forward declaration

class Interface
{
    public:
        Interface(int);
        ~Interface();
        unsigned int GetCounter();
        void SetCounter(unsigned int val);

    protected:

    private:
        Implementation *imp;

};

#endif // INTERFACE_H

در کلاس فوق دومتد دسترسی عمومی تعریف شده است و یک متغیر عضو اشاره گر به کلاس Implementation تعریف شده است.

نکته : در این کلاس ما با استفاده از forward declaration دیگر نیازی به وارد کردن هدر فایل  implementation.h نخواهیم داشت. البته توجه نمایید که اگر متغیر عضو imp راکه با استفاده از تکنیک ترکیب در این کلاس اشاره گر تعریف نمی کردیم در این صورت حتما باید هدر فایل Implementation.h را در هدر فایل Interface.h وارد میکردیم پس بنابراین استفاده از تکنیک کلاسهای وکیل بدون اشاره گر عملی نخواهد بود.

و سپس پیاده سازی کلاس اینترفیس را انجام می دهیم 

#include "Interface.h"
#include "Implemention.h"
//
Interface::Interface(int value)
         :imp(new Implementation(value)){
}

void Interface::SetCounter(unsigned int val){
  this->imp->SetCounter(val);
}

unsigned int Interface::GetCounter(){
  return this->imp->GetCounter();
}

Interface::~Interface()
{
    delete imp;
    this->imp =nullptr ;
}

پس بنابراین با توجه به نکات ذکر شده تا به اینجا شما فقط کافی است که هدر فایل Interface.h را در اختیار برنامه نویسان دیگر قرار دهید و فایلهایImplementation.h و همچنین فایل Interface.cpp را به صورت کامپایل شده در اختیار برنامه نویسان دیگر قرار دهید.

و در آخر هم برای استفاده از کلاس های فوق بدین ترتیب عمل خواهیم کرد.

#include <iostream>
#include "Interface.h"

using namespace std;

int main()
{
    Interface interface(7);
    cout << interface.GetCounter() << endl;

    interface.SetCounter(15);
    cout << interface.GetCounter() << endl;

    return 0;
}

با استفاده از تکنیک فوق در صورتی که هر گونه تغییری در آینده در پیاده سازی منطق های برنامه داشته باشید گیرنده های کلاس بدون متوجه شدن این تغییرات به کار خود ادامه خواهند داد.

دقیقا کاری که گروه استاندارد سازی زبان ++C همیشه انجام داده است و فقط نمای کتابخانه های استاندارد را در اختیار ما قرار میدهد و هرگونه تغییری در نحوه الگوریتم های این کتابخانه از دید ما مخفی هست ولازم به دانستن این تغییرات هم نخواهیم بود. 

  • پسندیدن 2
  • تشکر شده 1

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

برای ارسال دیدگاه یک حساب کاربری ایجاد کنید یا وارد حساب خود شوید

برای اینکه بتوانید دیدگاهی ارسال کنید نیاز دارید که کاربر سایت شوید

ایجاد یک حساب کاربری

برای حساب کاربری جدید در سایت ما ثبت نام کنید. عضویت خیلی ساده است !

ثبت نام یک حساب کاربری جدید

ورود به حساب کاربری

دارای حساب کاربری هستید؟ از اینجا وارد شوید

ورود به حساب کاربری

  • کاربران آنلاین در این صفحه   0 کاربر

    هیچ کاربر عضوی،در حال مشاهده این صفحه نیست.

  • مطالب مشابه

    • توسط فرهاد شیری
      کلاس Single Tone ژنریک با استفاده از اشاره گرهای هوشمند برای ساخت آبجکتی از یک کلاس با یک نمونه واحد برای صرفه جویی در حافظه مصرفی
      #ifndef SINGLETON_H #define SINGLETON_H #include <memory> namespace BP { template<typename CL> class SingleTone { protected: SingleTone() = default; // defualt ctor virtual inline ~SingleTone(){ delete instance; } private: static CL* instance; SingleTone(const SingleTone&) = delete; //copy ctor SingleTone(SingleTone&&) = delete ; //move ctor SingleTone& operator=(const SingleTone&) =delete ; // copy oprator assignment SingleTone& operator=(SingleTone&&) =delete ; // move oprator assignment static void destory(CL* my){ delete my ; instance = NULL; } public: std::unique_ptr<CL , decltype(&destory)> factory(){ //lazy instation if(instance == NULL){ instance = new CL(); } return std::unique_ptr<CL , decltype(&destory)>(instance , &destory); } }; template<typename CL> CL* SingleTone<CL>::instance = NULL; } #endif // SINGLETON_H ونحوه استفاده از کلاس فوق من کلاسی دارم برای ارتباط با پایگاه داده به نام DBProvider که در این کلاس متدی به نام OpenConnection را صدا زدم.
      توجه کنید که هر کلاسی که بخواهید را می توانید به حالت single tone ایجاد نمایید.
      روش اول فراخوانی
      db = SingleTone<DBProvider>::factory ()->OpenConnection () روش دوم فراخوانی
      db = (*SingleTone<DBProvider>::factory ()).OpenConnection (); فقط توجه داشته باشید که آبجکتهایی که single tone هستند یک اشاره گر واحد دارند بنابراین در کل برنامه یکسان خواهند بود.
×