Yazılım geliştirmede kalıp: bağdaştırıcı kalıbı

Adanali

Active member
Yazılım geliştirmede kalıp: bağdaştırıcı kalıbı


  1. Yazılım geliştirmede kalıp: bağdaştırıcı kalıbı

Modern yazılım geliştirmede şablonlar, açıkça tanımlanmış terminoloji ve temiz belgelerle önemli bir soyutlamadır. “Design Patterns: Elements of Reusable Object-Oriented Software” (kısaca Design Patterns) adlı klasik kitap, Adapter modeli dahil 23 model içerir. Temel fikri oldukça basittir: bir arayüzü başka bir arayüze dönüştürür.








Bağdaştırıcı modeli, yazılım geliştiricilerin müşterinin talep ettiği işlevselliği uygulayan bir sınıfa sahip olduğu ancak ilişkili arayüzün şirket politikasıyla tutarsız olduğu durumlarda özellikle kullanışlıdır. Bağdaştırıcı modeli, gerekli arabirimi mevcut sınıfla desteklemeyi kolaylaştırır.

Design Patterns: Elements of Reusable Object-Oriented Software (Tasarım Modelleri: Yeniden Kullanılabilir Nesne Yönelimli Yazılım Öğeleri) kitabında tartışılan tüm modeller arasında, yalnızca sınıf düzeyinde değil, aynı zamanda nesne düzeyinde de uygulanan tek Bağdaştırıcı modelidir.

Bu yapısal modeli uygulamanın iki yaygın yolunu göstermeden önce, temel gerçeklere hızlıca bir göz atalım:

adaptörün modeli


amaç

  • Bir arayüzü diğerine çevir

Ayrıca şöyle bilinir

kullanım durumu


  • Bir sınıf gerekli arabirime sahip değil
  • Bir dizi benzer sınıf için genel bir arayüzün tanımı
örnekler


Konteyner adaptörleri std::stack, std::queue Ve std::priority_queue dizi kapsayıcıları için özel bir arabirim sağlar. Aşağıdaki kod parçacığı, üç kapsayıcı adaptörünün model imzasını gösterir:


template<typename T, typename Container = std::deque<T>>
class stack;

template<typename T, typename Container = std::deque<T>>
class queue;

template<typename T, typename Container = std::vector<T>,
typename Compare = std::less<typename Container::value_type>>
class priority_queue;


Varsayılan olarak sığdır std::stack Ve std::queue içeren dizi std::deque; std::priority_queue kullanımda std::vector. Ayrıca gerekli std::priority_queue ikili bir yüklem. std::less varsayılan olarak kullanılır.

C++’ın başka bağdaştırıcıları vardır.

C++, ekleme yineleyicilerini ve akış yineleyicilerini destekler.

Üç ekleme yineleyicisi ile std::front_inserter, std::back_inserter Ve std::inserter bir öğe, bir kapsayıcının başına, sonuna veya herhangi bir yerine yerleştirilebilir.

Akış yineleyici bağdaştırıcıları, akışları bir veri kaynağı veya hedef olarak kullanabilir. C++ sırasıyla istream yineleyicileri ve ostream yineleyicileri oluşturmak için iki işlev sunar. Oluşturulan istream yineleyiciler girdi yineleyiciler gibi, ostream yineleyiciler ise ekleme yineleyiciler gibi davranır.

çerçeve


Aşağıdaki iki sınıf diyagramı, sınıf tabanlı veya nesne tabanlı bağdaştırıcı modelinin yapısını göstermektedir (Kısa olması için bunlara sınıf bağdaştırıcıları ve nesne bağdaştırıcıları diyeceğim).

sınıf adaptörü








nesne bağdaştırıcısı








müşteri

  • Üye işlevini kullanın methodA() adaptörün
adaptör

Sınıf:

  • işlevselliği sağlar methodA() çoklu kalıtım yoluyla kullanılabilir
  • itibaren halka açık olacak Interface ve özel Implementation türev
Nesne:

  • Üye fonksiyon çağrısını kendi Adaptee
uyarlanmış

  • İstemci işlevselliğini uygular
Bu noktada sınıf tabanlı mı yoksa nesne tabanlı mı bağdaştırıcı modelinin açık olması gerekir.

uygulama


sınıf adaptörü

Aşağıdaki örnekte, sınıf eşleşir RectangleAdapter arayüzü LegacyRectangle üzerinde.


// adapterClass.cpp

#include <iostream>

typedef int Coordinate;
typedef int Dimension;

class Rectangle {
public:
virtual void draw() = 0;
virtual ~Rectangle() = default;
};

class LegacyRectangle {
public:
LegacyRectangle(Coordinate x1, Coordinate y1, Coordinate x2, Coordinate y2) : x1_(x1), y1_(y1), x2_(x2), y2_(y2){
std::cout << "LegacyRectangle: create. (" << x1_ << "," << y1_ << ") => ("
<< x2_ << "," << y2_ << ")" << 'n';
}

void oldDraw() {
std::cout << "LegacyRectangle: oldDraw. (" << x1_ << "," << y1_
<< ") => (" << x2_ << "," << y2_ << ")" << 'n';
}

private:
Coordinate x1_;
Coordinate y1_;
Coordinate x2_;
Coordinate y2_;
};


class RectangleAdapter : public Rectangle, private LegacyRectangle {
public:
RectangleAdapter(Coordinate x, Coordinate y, Dimension w, Dimension h) : LegacyRectangle(x, y, x + w, y + h) { // (1)
std::cout << "RectangleAdapter: create. (" << x << "," << y
<< "), width = " << w << ", height = " << h << 'n';
}

void draw() override {
oldDraw();
std::cout << "RectangleAdapter: draw." << 'n';
}
};

int main() {

std::cout << 'n';

Rectangle* r = new RectangleAdapter(120, 200, 60, 40);
r->draw();

delete r;

std::cout << 'n';

}


RectangleAdapter çoklu kalıtım sayesinde teşekkürler arayüzüne sahiptir Rectangle ve uygulanması LegacyRectangle. Artı, yakışıyor RectangleAdapter boyutu LegacyRectangle yukarı (satır 1).

Bağdaştırıcı modelinin bu uygulaması, özel kalıtımın nadir kullanım durumlarından biridir. Buna arayüz kalıtımı ve uygulama kalıtımı hakkında birkaç kelime eklemek istiyorum:

  • the arayüz kalıtımı genel mirası kullanın. Temel sınıfın kullanıcılarını etkilemeden türetilmiş sınıfların eklenebilmesi ve değiştirilebilmesi için kullanıcıları uygulamadan ayırın. Türetilmiş sınıflar, temel sınıf arayüzünü destekler.
  • İçinde uygulama mirası özel miras sıklıkla kullanılır. Tipik olarak, türetilmiş sınıf, temel sınıfın işlevselliğini uyarlayarak kendi işlevselliğini sağlar. Türetilmiş sınıflar, temel sınıf arayüzünü desteklemez.
Son olarak programın çıktısı şu şekildedir:








nesne bağdaştırıcısı


Aşağıdaki uygulama, RectangleAdapterçağrıları bağdaştırıcısına devret LegacyRectangle.


// adapterObject.cpp

#include <iostream>

typedef int Coordinate;
typedef int Dimension;

class LegacyRectangle {
public:
LegacyRectangle(Coordinate x1, Coordinate y1, Coordinate x2, Coordinate y2) : x1_(x1), y1_(y1), x2_(x2), y2_(y2){
std::cout << "LegacyRectangle: create. (" << x1_ << "," << y1_ << ") => ("
<< x2_ << "," << y2_ << ")" << 'n';
}

void oldDraw() {
std::cout << "LegacyRectangle: oldDraw. (" << x1_ << "," << y1_
<< ") => (" << x2_ << "," << y2_ << ")" << 'n';
}

private:
Coordinate x1_;
Coordinate y1_;
Coordinate x2_;
Coordinate y2_;
};

class RectangleAdapter {
public:
RectangleAdapter(Coordinate x, Coordinate y, Dimension w, Dimension h) : legacyRectangle{LegacyRectangle(x, y, x + w, y + h)} { // (1)
std::cout << "RectangleAdapter: create. (" << x << "," << y
<< "), width = " << w << ", height = " << h << 'n';
}

void draw() {
legacyRectangle.oldDraw();
std::cout << "RectangleAdapter: draw." << 'n';
}
private:
LegacyRectangle legacyRectangle;
};

int main() {

std::cout << 'n';

RectangleAdapter r(120, 200, 60, 40);
r.draw();

std::cout << 'n';
}


Sınıf RectangleAdapter sen yarat LegacyRectangle doğrudan yapıcılarında (satır 1). Başka bir olasılık da şu olurdu: LegacyRectangle yapıcı parametresi olarak RectangleAdapter kullanmak.


class RectangleAdapter {
public:
RectangleAdapter(const LegacyRectangle& legRec): legacyRectangle{legRec} {}
...
};


Bu programın çıktısı bir öncekiyle aynıdır.

İlgili tasarım desenleri

  • Köprü modeli, Nesne Bağdaştırıcısına benzer, ancak farklı bir amaca sahiptir. Köprü modelinin amacı arayüzü uygulamadan ayırmak iken adaptörün amacı mevcut bir arayüzü değiştirmektir.
  • Dekoratör deseni, arayüzünü değiştirmeden bir nesneyi genişletir. Dekoratörler birbirine geçebilir, ancak köprüler veya bağdaştırıcılar birbirine kenetlenemez.
  • Proxy modeli, temsil ettiği nesnenin uygulamasını genişletir ancak arayüzünü değiştirmez.
Şimdi soru ortaya çıkıyor, hangi durumda sınıf bağdaştırıcısı kullanılmalı ve nesne bağdaştırıcısı ne zaman kullanılmalıdır?

Sınıf bağdaştırıcısına karşı nesne bağdaştırıcısı


Sınıf bağdaştırıcısı, sınıfları ve alt sınıflarını zorlar. Arayüz, uygulama ve sanal işlev çağrılarının ayrılmasını kullanın. İşlevselliği sabit kodlanmıştır ve derleme zamanında kullanılabilir. Sınıf bağdaştırıcısı daha az esneklik sunar ve nesne bağdaştırıcısı gibi dinamik davranışlardan yoksundur.

Nesne bağdaştırıcısı, nesne ilişkisini kullanır. Soyutlama, nesneleri bir araya getirerek ve işlerini devrederek oluşturulabilir. Bu kompozisyon çalışma zamanında yapılabilir. Sonuç olarak, bir nesne bağdaştırıcısı daha esnektir ve çalışma zamanında delege nesnesinin değiştirilmesine izin verir.

Sıradaki ne?


Köprü modeli, arabirimi uygulamasından ayırmaya yardımcı olur. Bir sonraki yazımda daha detaylı olarak sunacağım.


(harita)



Haberin Sonu
 
Üst