Yazılım geliştirmede kalıplar: köprü kalıbı

Adanali

Active member
Yazılım geliştirmede kalıplar: köprü kalıbı


  1. Yazılım geliştirmede kalıplar: köprü kalıbı

Kalıplar, modern yazılım geliştirmede önemli bir soyutlamadır. İyi tanımlanmış terminoloji, açık belgeler sunar ve en iyisinden öğrenirler. “Design Patterns: Elements of Reusable Object-Oriented Software” (kısaca Design Patterns) adlı klasik kitap, yapısal modellerden biri olan köprü deseni de dahil olmak üzere 23 model içerir. Arayüzü uygulamasından ayırın. Basitleştirilmiş bir sürüm genellikle C++’da kullanılır: Pimpl deyimi.







Rainer Grimm, uzun yıllardır yazılım mimarı, ekip lideri ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanır, aynı zamanda sık sık uzmanlık konferanslarında konuşmaktan da keyif alır. Modernes C++ blogunda yoğun bir şekilde C++ tutkusundan bahsediyor.













Pimpl deyimi hakkında yazmadan önce, işte köprü şeması hakkındaki gerçekler.

köprü modeli


amaç

  • Arayüzü uygulamadan ayırın
Ayrıca şöyle bilinir


  • Kulp/Gövde
  • Pimpl (uygulamaya işaretçi) deyim
uygulanabilirlik

  • Arayüz ve uygulama genişletilebilir
  • Uygulamanın arayüzünü değiştirmenin istemci üzerinde hiçbir etkisi yoktur.
  • Uygulama gizli
çerçeve









Abstraktion

  • Soyutlamanın arayüzünü tanımlar
  • tipinde bir nesnesi var Implementor
RedefinedAbstraction

  • Arayüzünü uygulayın veya iyileştirin Abstraction
Implementor

  • Uygulama arayüzünü tanımlar
ConcreteImplementor

  • Arayüzünü uygula Implementor
Köprü modelinin iki hiyerarşisi vardır: biri soyutlama (arayüz) ve diğeri uygulama içindir. Soyutlama ve soyutlamaya karşı istemci programları, uygulamayı tüketir. Sonuç olarak, soyutlama arayüzünün farklı uygulamaları ve uygulama arayüzünün farklı uygulamaları şeffaf bir şekilde kullanılabilir. Köprü modeli, soyutlama ve uygulama değişkenlik gösterebileceği ve program çalışma zamanında değiştirilebileceği için büyük esneklik sunar.

Köprü motifi, miras ve kompozisyonu birleştirmenin güzel bir örneğidir. Bir yandan iki tür hiyerarşiye (kalıtım) sahiptir ve diğer yandan soyutlamanın bir uygulamasına (kompozisyon) sahiptir.

misal

Örnek, köprü modelinin basit bir uygulamasını gösterir.


// bridge.cpp

#include <iostream>

class Implementor { // (1)
public:
virtual void implementation() const = 0;

virtual ~Implementor() = default;
};

class ImplementorA: public Implementor {
public:
ImplementorA() = default;

void implementation() const {
std::cout << "ImplementatorA::implementation" << 'n';
}
};

class ImplementorB: public Implementor {
public:
ImplementorB() = default;

void implementation() const {
std::cout << "ImplementatorB::implementation" << 'n';
}
};

class Abstraction { // (2)
public:
virtual void function() const = 0;
virtual ~Abstraction() = default;
};

class RefinedAbstraction: public Abstraction {
public:
RefinedAbstraction(Implementor& impl) :
implementor(impl) {
}

void function() const {
std::cout << "RefinedAbstraction::functionn";
implementor.implementation();
}
private:
Implementor& implementor;
};

int main() {

std::cout << 'n';

ImplementorA implementorA;
ImplementorB implementorB;

RefinedAbstraction refinedAbstraction1(implementorA); // (3)
RefinedAbstraction refinedAbstraction2(implementorB); // (4)

Abstraction *abstraction1 = &refinedAbstraction1;
Abstraction *abstraction2 = &refinedAbstraction2;

abstraction1->function();

std::cout << 'n';

abstraction2->function();

std::cout << 'n';

}


Sınıf Implementor (1), uygulama hiyerarşisine ve sınıfa arabirimdir Abstraction (2) soyutlama için arayüz. örnekler redefinedAbstraction1 Ve redefinedAbstraction2 uygulamalarını yapıcılarında (3 ve 4) alın.

Aşağıdaki ekran görüntüsü programın çıktısını göstermektedir.








İlgili modeller

  • Bağdaştırıcı deseni, bir bağdaştırıcı nesnesi olarak uygulandığında, köprü düzenine benzer ancak amacı farklıdır. Köprü modelinin amacı arayüzü uygulamadan ayırmak iken adaptörün amacı mevcut bir arayüzü değiştirmektir.
Köprü deseninin basitleştirilmiş bir versiyonu genellikle C++’da kullanılır.

sivilce dili


pimpl deyiminin özü, sınıfın uygulanmasının bir işaretçinin arkasına gizlenmiş olmasıdır.

İşte pimpl deyimini uygulamak için bir tarif:

  • Özel verileri ve sınıf üye işlevlerini taşıyın (Kamusal sınıf) ayrı bir sınıfta (sivilce sınıfı).
  • beyan etmek sivilce sınıfı genel sınıfın başlığında.
  • Tip işaretçisini bildir sivilce sınıfı içinde Kamusal sınıf.
  • tanımla sivilce sınıfı kaynak dosyasındaki Kamusal sınıf.
  • örneğini oluştur sivilce sınıfı yapıcısında Kamusal sınıfSt.
  • Üye fonksiyonları Kamusal sınıf işlevlerini kullanmak sivilce sınıfıSt.
Bartlomiej Filipek, “The Pimpl Pattern – ne bilmeniz gerekir” adlı blog yazısında Pimpl deyiminin güzel bir örneğini veriyor:


// class.h
class MyClassImpl;
class MyClass
{
public:
explicit MyClass();
~MyClass();

// movable:
MyClass(MyClass && rhs) noexcept; // (2)
MyClass& operator=(MyClass && rhs) noexcept; // (3)

// and copyable
MyClass(const MyClass& rhs); // (4)
MyClass& operator=(const MyClass& rhs); // (5)

void DoSth();
void DoConst() const;

private:
const MyClassImpl* Pimpl() const
{ return m_pImpl.get(); } // (6)
MyClassImpl* Pimpl() { return m_pImpl.get(); } // (7)

std::unique_ptr<MyClassImpl> m_pImpl; // (1)
};

// class.cpp
class MyClassImpl
{
public:
~MyClassImpl() = default;

void DoSth() { }
void DoConst() const { }
};

MyClass::MyClass() : m_pImpl(new MyClassImpl())
{

}

MyClass::~MyClass() = default;
MyClass::MyClass(MyClass &&) noexcept = default;
MyClass& MyClass::eek:perator=(MyClass &&) noexcept = default;

MyClass::MyClass(const MyClass& rhs)
: m_pImpl(new MyClassImpl(*rhs.m_pImpl))
{}

MyClass& MyClass::eek:perator=(const MyClass& rhs) {
if (this != &rhs)
m_pImpl.reset(new MyClassImpl(*rhs.m_pImpl));

return *this;
}

void MyClass::DoSth()
{
Pimpl()->DoSth();
}

void MyClass::DoConst() const
{
Pimpl()->DoConst();
}


Bunlar, uygulanmasının ana fikirleridir. Bazı satır işaretleri ekledim:

  • sivilce bir std::unique_ptr<MyClassImpl> (1)
  • Sınıf, kopyalama ve taşıma semantiğini destekler (2 – 5)
  • özel olanlar Pimp()-Üyelerin işlevleri MyClass bir tane ver const ve değilconst MyClassImpl-el geri (6 ve 7)
Pimpl dilinin avantajları nelerdir? uygulamak daha kolay olurdu MyClassImpl soyutlamada MyClass içermek

Avantajlar ve dezavantajlar


Faydalarından başlayayım

yarar

  • İkili uyumluluk: Uygulamanın değiştirilmesi, soyutlamayı kullanan istemci için arabirimi değiştirmez.
  • derleme zamanı: Uygulama değişiklikleri, soyutlama kullanılarak istemcinin yeniden derlenmesini gerektirmez. Bu nedenle, Pimpl deyimine genellikle bir yapı güvenlik duvarı denir. C++20’deki modüller de bu avantajlara sahiptir.
  • genişletilebilirlikt: Uygulamayı çalışma zamanında değiştirmek yeterince kolaydır. Genel olarak, sanallığa gerek yoktur.
Dezavantajları

  • verim: İşaretçi yeniden yönlendirme, ekstra çalışma zamanı maliyetlerine neden olur.
  • büyük altı: Büyük Altı’yı göz önünde bulundurmalısınız (bkz. “C++ Temel Yönergeleri: Sıfırların, Beşlerin veya Altıların Kuralı”). neden soyutlama std::unique_ptr kopya anlamını desteklemiyor. Bu özel durumda, bunun anlamı:
    • Gerekirse kopya anlambilim uygulamanız gerekir.
    • Kopya semantiğini uyguladığınızda, otomatik olarak taşıma semantiği almazsınız.
  • bellek tahsisi: Pimpl deyimi, bir bellek tahsisi gerektirir. Bu, gömülü sistemlerde mümkün olmayabilir ve bellek parçalanmasına yol açabilir.
Sıradaki ne?


Dekoratör Modeli, “Design Patterns: Elements of Reusable Object-Oriented Software” kitabından yaygın olarak kullanılan bir yapısal modeldir. Görevi, bir nesneyi sorumlulukla dinamik olarak genişletmektir. Dekoratörü bir sonraki yazımda daha detaylı tanıtacağım.


()



Haberin Sonu
 
Üst