桥接模式

2018-08-02-09-55-20

如果有单个变化,通过继承类+虚函数实现。当有多个变化时,变得复杂不好维护。将继承关系变为耦合关系,即 Bridge 模式,即好处是相对多层继承来的.

使用 bridge 时,特别要注意,一个类可能具有的独立变化的维度,这个维度可以拿出来抽象.

用书上的例子, 蜡笔 3 种型号+12 种颜色需要 36 种组合,而毛笔仅需要 3 种型号+12 种颜色, 因为毛笔将型号和颜色解耦了, 通过组合型号和颜色两个性质,而不是通过继承具体的型号和颜色.

这种思路应该还蛮常见的, 没有哪个傻子去用 36 个类的把…

根据自己的项目模拟的实际例子.

Client 就是 Mirror, Implementor 就是抽象的 Encoder 和 Channel

Abstraction 就是 Mirror 里的方法,这里没有用继续继承 Mirror,也就是 RedefinedAbstraction.

#include <iostream>


#include <string>
using std::string;
using std::cout;
//
class Encoder  {
    public:
        virtual void setEncoder(const string & s) = 0;
        virtual ~Encoder(){}
};

class Channel {
    public:
        virtual void connect() = 0;
        virtual void send() = 0;
        virtual ~Channel(){}
};

class JpegEncoder : public Encoder {
    public:
        void setEncoder(const string & s) {cout << "setup jpeg  encoder " << s << "\n";}
        virtual ~JpegEncoder(){}
};

class H264Encoder : public Encoder {
    public:
        void setEncoder(const string & s) {cout << "setup h264  encoder " << s << "\n";}
        virtual ~H264Encoder(){}
};

class WifiChannel : public Channel {
    public:
        void connect() {cout << "Wifi connect\n";}
        void send() {cout << "Wifi send\n";}
        virtual ~WifiChannel(){}
};

class UsbChannel : public Channel {
    public:
        void connect() {cout << "Usb connect\n";}
        void send() {cout << "Usb send\n";}
        virtual ~UsbChannel(){}
};

class Mirror {
    public:
        Mirror(Channel* c, Encoder* e):chn(c),encoder(e) {}
        void openChannel() { chn->connect();}
        void initEncoder(const string & s) {encoder->setEncoder(s);}
    private:
        //bridge的核心在这,通过基类指针指向不同的派生类,抽象了具体实现,
        //而且不同的变化间独立,可用不同的基类指针
        //更桥接一点,应该使用Mirror的派生,派生出
        //wifi-jpeg mirror 之类的东西?
        Channel* chn;
        Encoder* encoder;
};


int main(int argc, char* argv[])
{
    Channel* c = new WifiChannel();
    Encoder* e = new H264Encoder();
    Mirror m(c, e);
    m.openChannel();
    m.initEncoder("ex1");

    Channel* c1 = new UsbChannel();
    Encoder* e1 = new JpegEncoder();
    Mirror m1(c1, e1);
    m1.openChannel();
    m1.initEncoder("ex2");


    return 0;
}