C++中设计模式——适配器模式(Adapter模式)

适配器

概述

适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

用适配器配出栈和队列

 用顺序表和链表适配出栈和队列。
用适配器适配出栈

template <class T,class Container> //普通模板参数

class Stack
{
public:
    void StackPush(const T& s){_con.PushBack(s);} //入栈
    void StackPop(){_con.PopBack();}//出栈
    T& StackTop(){return _con.Back();}//取得栈顶元素
    bool StackEmpty(){return _con.Empty();}//判断栈是否为空
protected:
    Container _con; //普通模板参数
};

测试

void StackTest()
{
    Stack<int,Vector<int>> s;
    s.StackPush(1);
    s.StackPush(2);
    s.StackPush(3);
    s.StackPush(4);
    s.StackPush(5);

    while (!s.StackEmpty())
    {
        cout<<s.StackTop()<<" ";
        s.StackPop();
    }
    cout<<endl;

    Stack<string,List<string>> s1;
    s1.StackPush("hello");
    s1.StackPush("world");
    s1.StackPush("welcome");
    s1.StackPush("you");
    s1.StackPush("!");

    while (!s1.StackEmpty())
    {
        cout<<s1.StackTop()<<" ";
        s1.StackPop();
    }
    cout<<endl;
}

栈

这样我们就很轻松的利用顺序表和链表适配出了栈
用适配器适配出队列

template<class T,class Container>
class Queue
{
public:
    void PushBack(const T& q){_con.PushBack(q);}//入队
    void PopFront(){_con.PopFront();}//出队
    T& Front(){return _con.Front();}//取队头元素
    int Size(){return _con.Size();}//求队列大小
    bool Empty(){return _con.Empty();}//判断队列是否为空
protected:
    Container _con;
};

测试

void QueueTest()
{
    Queue<int,Vector<int>> q;
    q.PushBack(1);
    q.PushBack(2);
    q.PushBack(3);
    q.PushBack(4);
    q.PushBack(5);

    while (!q.Empty())
    {
        cout<<q.Front()<<" ";
        q.PopFront();
    }
    cout<<endl;

    Queue<string,List<string>> q1;
    q1.PushBack("change");
    q1.PushBack("my");
    q1.PushBack("world");
    q1.PushBack("come");
    q1.PushBack("on !");

    while (!q1.Empty())
    {
        cout<<q1.Front()<<" ";
        q1.PopFront();
    }
    cout<<endl;
}

队列
这样我们就很轻松的利用顺序表和链表适配出了队列

模板的模板参数

上面看起来已经解决了问题,但是如果我不小心这样写了这样的代码:

void QueueTest()
{
    Queue<int,Vector<char>> q; //两个类型不一样
    Queue<string,List<int>> q1; //两个类型不一样

}

这样的话是不是就会很坑,妥妥的错。为了防止你写出这样的代码,有一种模板参数的方式就杜绝了这种不必要的麻烦。

template <class T,template<class> class Container> //模板的模板参数
class Stack
{
public:
    void StackPush(const T& s){_con.PushBack(s);} //入栈
    void StackPop(){_con.PopBack();}//出栈
    T& StackTop(){return _con.Back();}//取得栈顶元素
    bool StackEmpty(){return _con.Empty();}//判断栈是否为空
protected:
    Container<T> _con; //模板的模板参数
};

如果这样写就很好解决了防止你把类型传的不一样而导致不必要的错误。

模板的非类型参数
非类型类模板参数

举个例子,假如你要实现动态数组,而且在一个函数里面要用到不同类型的数组,那我们就可以这样。直接看代码:

template<class T,size_t N>
class Array
{
protected:
    T array[N];
};
非类型函数模板参数
template<class T,size_t N>
T Add(const T& x)
{
    return x+N;
}
非类型模板参数的限制
  • 它可以是常整数(包括enum枚举类型)或者指向外部链接对象的指针。
  • 浮点数和类对象(class-type)不允许作为非类型模板参数
  • 非类型模板参数可以是指针,但该指针必须指向外部链接对象
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙跃十二

写的不错,给点鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值