• 适配器模式(Adapter)


    1、作用

    名字很形象的说出了模式的作用:当有一个需求需要Target的接口,然后有一个现成的Adaptee接口,为了让Adaptee接口匹配上Target接口,就需要使用Adapter,在Adapter中将Adaptee适配Target。

    Adapter和Bridge模式都使用了关联关系,Bridge中关联的两个类都可以扩展,Adapter中只会扩展Target产生新的Adapter,Adatee是固定不修改了。

    2、实现方式

    实现Adapter适配器设计模式有两种方式:组合(compositon, has-a关系)和继承(inheritance,is-a关系)。

    对象适配器模式使用组合,UML图如下:

    就是Aapter里实际上包含一个被适配的对象。(组合)又继承了target。因此如果要用到target的方法,直接调用父类的方法,如果要用到被适配者的方法, 就调用内部成员的函数。

    3、C++代码

    STL里的stack和queue都是adapter,底层是deque,隐藏了deque的一些接口,使得其可以达到FIFO是queue,LIFO是stack。

    下面用适配器模式模拟将deque生成queue和stack接口。

    SequentialContainer.h

    #include <deque>
    
    #ifndef __QUEUE__H__
    #define __QUEUE__H__
    
    
    template<typename T>
    class SequentialContainer {
        public:
            SequentialContainer() = default;
            virtual ~SequentialContainer() {} // 虚析构函数
            virtual void put(const T &v) = 0;
            virtual T pop() = 0;
    };
    
    template<typename T>
    class Stack:public SequentialContainer<T> {
        public:
            Stack(std::deque<T> *dq):dq(dq){}
            ~Stack() { delete dq; } // 析构指针对象指向的空间
            void put(const T &v) override { dq->emplace_front(v);}
            T pop() override {
                if(dq->size()>0){
                    int tmp =  dq->front();
                    dq->pop_front();
                    return tmp;
                } else {
                    return 0;
                }
            }
        private:
            std::deque<T> *dq;
    };
    
    
    template<typename T>
    class Queue:public SequentialContainer<T> {
        public:
            Queue(std::deque<T> *dq):dq(dq){}
            ~Queue() { delete dq; } // 析构指针对象指向的空间
            void put(const T &v) override { dq->emplace_front(v);}
            T pop() override {
                int tmp =  dq->back();
                dq->pop_back();
                return tmp;
            }
        private:
            std::deque<T> *dq;
    };
    
    #endif

    test.h

    #include <iosteam>
    #include <deque>
    #include "SequntialContainer.h"

    using namespace std; int main() { SequentialContainer<int> *stack = new Stack<int>(new deque<int>); SequentialContainer<int> *queue = new Queue<int>(new deque<int>); for(int i=0; i<10; ++i){ stack->put(i); queue->put(i); } cout<<"stack output:"; for(int i=0; i<11; ++i) cout<<stack->pop()<<" "; cout<<endl; cout<<"fifo output:"; for(int i=0; i<11; ++i) cout<<queue->pop()<<" "; cout<<endl;

        delete stack; // 析构动态生成的对象
        delete queue;
      return 0; 
    }

    输出:

     超出队列或者stack的长度后,输出都是0.

    Adpter中不保存Adaptee的指针,而是对象,这样就不要析构函数了。

    SequentialContainer.h

    #include <deque>
    
    #ifndef __QUEUE__H__
    #define __QUEUE__H__
    
    
    template<typename T>
    class SequentialContainer {
        public:
            SequentialContainer() = default;
            virtual ~SequentialContainer(){} // 虚析构函数
            virtual void put(const T &v) = 0;
            virtual T pop() = 0;
    };
    
    template<typename T>
    class Stack:public SequentialContainer<T> {
        public:
            Stack(std::deque<T> dq):dq(dq){}
            void put(const T &v) override { dq.emplace_front(v);}
            T pop() override {
                if(dq.size()>0){
                    int tmp =  dq.front();
                    dq.pop_front();
                    return tmp;
                } else {
                    return 0;
                }
            }
        private:
            std::deque<T> dq;
    };
    
    
    template<typename T>
    class Queue:public SequentialContainer<T> {
        public:
            Queue(std::deque<T> dq):dq(dq){}
            void put(const T &v) override { dq.emplace_front(v);}
            T pop() override {
                int tmp =  dq.back();
                dq.pop_back();
                return tmp;
            }
        private:
            std::deque<T> dq;
    };
    
    #endif

    test.cc

    #include <iostream>
    #include "SequentialContainer.h"
    
    using namespace std;
    
    int main() {    
        SequentialContainer<int> *stack = new Stack<int>(deque<int>());
        SequentialContainer<int> *queue  = new Queue<int>(deque<int>());
    
        for(int i=0; i<10; ++i){
            stack->put(i);
            queue->put(i);
        }
    
        cout<<"stack output:";
        for(int i=0; i<11; ++i)
            cout<<stack->pop()<<" ";
        cout<<endl;
    
        cout<<"queue output:";
        for(int i=0; i<11; ++i)
            cout<<queue->pop()<<" ";
        cout<<endl;
    
        delete stack; // 析构动态生成的对象
        delete queue;
    
        return 0;
    }
  • 相关阅读:
    LeetCode 914. 卡牌分组
    LeetCode 999. 车的可用捕获量
    LeetCode 892. 三维形体的表面积
    21航电5E
    min25筛 学习笔记
    牛客多校6G
    2021航电多校3
    2021牛客多校H
    [模版] 快速傅里叶变换
    2021牛客多校第五场
  • 原文地址:https://www.cnblogs.com/yuandonghua/p/11840206.html
Copyright © 2020-2023  润新知