(19) 桥接模式 Bridge,不是采用类继承,而是采用类组合,一个类的数据成员是类对象,来扩展类的功能。源码如下:
class OS // 操作系统负责绘图
{
public:
virtual ~OS() {}
virtual void draw(char * ptrCache , int lengthCache) = 0 ;
};
class OS_Window : public OS
{
public:
void draw(char* ptrCache, int lengthCache) { cout << " windows 下绘图\n\n"; }
};
class OS_Linux : public OS
{
public:
void draw(char* ptrCache, int lengthCache) { cout << " Linux 下绘图\n\n"; }
};
class Image // 本基类有成员函数负责解析与加载图片至缓存,但绘图调用跟操作系统有关的底层函数
{
protected: OS * ptrOS;
public:
virtual ~Image() {}
Image(OS* p) : ptrOS(p) {}
virtual void parseImage( const char * name) = 0;
};
class Image_jpg : public Image
{
public:
Image_jpg(OS * p) : Image(p){}
void parseImage(const char* name)
{
cout << " 解析 jpg 图片 , ";
char c[100]; // 假定分析 jpg 格式后的图片信息统一用 100 字节存储。
ptrOS->draw(c , 100);
}
};
class Image_png : public Image
{
public:
Image_png(OS* p) : Image(p) {}
void parseImage( const char* name)
{
cout << " 解析 png 图片 , ";
char c[50]; // 假定分析 png 格式后的图片信息统一用 50 字节存储。
ptrOS->draw(c, 50);
}
};
int main()
{
OS_Window osWindow;
OS_Linux osLinux;
Image_jpg jpgA(&osLinux) , jpgB(&osWindow) ;
Image_png pngA(&osLinux) , pngB(&osWindow) ;
jpgA.parseImage("aaa");
jpgB.parseImage("b");
pngA.parseImage("c");
pngB.parseImage("dd");
return 0;
}
测试结果如下:
(20)中介者模式 Mediator 。比如 UI 设计,页面上的各种控件,牵一发而动全身,彼此联系紧密。若把控件间的联系代码写入各个控件,会很繁琐,庞大。因此可以创建一个中介对象,专门处理当一个 UI 控件的状态变化时的逻辑。也像电脑主板上的总线,借着总线,实现电脑各部件见的连接与通信。以下代码配套的是这个 UI 登录界面:
配套的代码如下:
class Control; // 类的前向声明
class Media // 中介者的基类
{
public:
virtual ~Media() {}
virtual void changed(Control * ptrCtrl) = 0;
};
class Control // 控件的基类
{
protected:
string name; // 控件名称,以此区分控件,所以该名称将是唯一的
Media* ptrMedia; // 显示本控件属于哪个中介管理
public:
virtual ~Control() {}
Control(const string& s, Media* pM) : name(s), ptrMedia(pM) {}
virtual void enable(bool enabled) = 0;
virtual void changed() { ptrMedia->changed(this); } // 控件产生了变化,交由 中介者 来处理这种相关联的变化
};
class Control_Button : public Control
{
public:
Control_Button(const string& s, Media* ptr) : Control(s, ptr) {}
void enable(bool enabled)
{
if (enabled)
cout << " 按钮 " << name << " 被启用\n\n";
else
cout << " 按钮 " << name << " 被禁用\n\n";
}
};
class Control_Radio : public Control
{
public:
Control_Radio(const string& s, Media* ptr) : Control(s, ptr) {}
void enable(bool enabled) {} // 对于单选按钮,不必使用此函数
void select(bool clicked) // 对于单选按钮,增加此函数
{
if(clicked)
cout << " 单选按钮 " << name << " 被启用\n\n";
else
cout << " 单选按钮 " << name << " 被禁用\n\n";
}
};
class Control_text : public Control
{
private : string text; // 文本框里保存了账号或密码的内容
public:
Control_text(const string & t , const string& s, Media* ptr) : text(t) , Control(s, ptr) {}
Control_text(const string& s, Media* ptr) : text(""), Control(s, ptr) {}
void enable(bool enabled)
{
if (enabled)
cout << " 文本框 " << name << " 被启用\n\n";
else
cout << " 文本框 " << name << " 被禁用\n\n";
}
void setText(const string& s) { text = s; } // 对文本框增加此函数
bool isEmpty() { return text.empty(); } // 判断文本框是否为空
};
class Media_UI : public Media
{
private:
Control_Button* pLogin, * pLogout;
Control_Radio* pRadioTourist, * pRadioAccount;
Control_text *pTextName, * pTextPwd;
public:
Media_UI(){}
void init(Control_Button* pLin, Control_Button*pLout, Control_Radio* pTourist, Control_Radio* pAccount, Control_text* pName, Control_text* pPwd)
{
pLogin = pLin; pLogout = pLout;
pRadioTourist = pTourist; pRadioAccount = pAccount;
pTextName = pName; pTextPwd = pPwd;
}
virtual void changed(Control* ptrCtrl)
{
if (ptrCtrl == pLogout) { cout << " 游戏退出!\n\n"; return; }
if (ptrCtrl == pRadioTourist)
{
pRadioTourist->select(true);
pRadioAccount->select(false);
pTextName->enable(false);
pTextPwd->enable(false);
pLogin->enable(true);
return;
}
if (ptrCtrl == pLogin) { cout << " 开始登录验证\n\n"; }
if (ptrCtrl == pRadioAccount)
{
pRadioTourist->select(false);
pRadioAccount->select(true);
pTextName->enable(true);
pTextPwd->enable(true);
if (pTextName->isEmpty() || pTextPwd->isEmpty())
pLogin->enable(false);
else
pLogin->enable(true);
}
if (ptrCtrl == pTextName || ptrCtrl == pTextPwd)
{
if (pTextName->isEmpty() || pTextPwd->isEmpty())
pLogin->enable(false);
else
pLogin->enable(true);
}
}
};
int main()
{
Media_UI media_UI;
Control_Button login("登录", &media_UI), logout("退出" , &media_UI);
Control_Radio tourist("游客登录", &media_UI), account("账户登录" , &media_UI);
Control_text name("昵称", &media_UI), password("密码" , &media_UI);
media_UI.init(&login , &logout , & tourist , & account , & name , & password);
login.changed(); logout.changed();
tourist.changed(); account.changed();
name.changed(); password.changed();
name.setText("aaa"); password.setText("1234556");
login.changed(); account.changed(); name.changed();
return 0;
}
测试结果如下:
(21)
谢谢