设计模式之前只记录了一部分,然后最近在看李建总老师中的设计模式,发现讲解的非常好,于是补充下代码,与记录对应的类图,希望看过的同学,可以跑通代码,毕竟老师只是讲解具体过程。喜欢我博客的同学可以关注我,让我们共同进步,让自己的代码写的更加好。
视频链接:桥模式
“单一职责”模式:
在软件组件的设计中,如果责任划分的不清楚,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。
典型模式:
- Decorator
- Bridge
动机
由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个维度的变化。
比如我常用的代码写方式,原因是因为我们太懒,不爱画类图,上来就写代码,如下面的例子:
#pragma once
#include "stdafx.h"
class Messager {
public:
virtual void Login(string usrname, string password) = 0;
virtual void SendMessage(string message) = 0;
virtual void SendPicture(string image) = 0;
virtual void PlaySound() = 0;
virtual void DrawShape() = 0;
virtual void WriteText() = 0;
virtual void Connect() = 0;
virtual ~Messager() {}
};
//平台实现
class PCMessagerBase : public Messager {
public:
virtual void PlaySound()
{
cout << "PCMessagerBase PlaySound "<< endl;
}
virtual void DrawShape()
{
cout << "PCMessagerBase DrawShape " << endl;
}
virtual void WriteText()
{
cout << "PCMessagerBase WriteText " << endl;
}
virtual void Connect()
{
cout << "PCMessagerBase Connect " << endl;
}
};
class MobileMessagerBase : public Messager {
public:
virtual void PlaySound()
{
cout << "MobileMessagerBase PlaySound " << endl;
}
virtual void DrawShape()
{
cout << "MobileMessagerBase DrawShape " << endl;
}
virtual void WriteText()
{
cout << "MobileMessagerBase WriteText " << endl;
}
virtual void Connect()
{
cout << "MobileMessagerBase Connect " << endl;
}
};
//业务抽象
class PCMessagerLite : public PCMessagerBase
{
virtual void Login(string usrname, string password)
{
PCMessagerBase::Connect();
cout << "PCMessagerLite " << usrname << "Login IN" << endl;
}
virtual void SendMessage(string message)
{
PCMessagerBase::WriteText();
cout << "PCMessagerLite message is " << message << " " << endl;
}
virtual void SendPicture(string image)
{
PCMessagerBase::DrawShape();
}
};
class PCMessagerPerfect : public PCMessagerBase
{
virtual void Login(string usrname, string password)
{
PCMessagerBase::PlaySound();
PCMessagerBase::Connect();
cout << "PCMessagerLite " << usrname << "Login IN" << endl;
}
virtual void SendMessage(string message)
{
PCMessagerBase::PlaySound();
PCMessagerBase::WriteText();
cout << "PCMessagerLite message is " << message << " " << endl;
}
virtual void SendPicture(string image)
{
PCMessagerBase::PlaySound();
PCMessagerBase::DrawShape();
}
};
class MobileMessagerLite : public MobileMessagerBase
{
virtual void Login(string usrname, string password)
{
MobileMessagerBase::Connect();
cout << "MobileMessagerBase " << usrname << "Login IN" << endl;
}
virtual void SendMessage(string message)
{
MobileMessagerBase::WriteText();
cout << "MobileMessagerBase message is " << message << " " << endl;
}
virtual void SendPicture(string image)
{
MobileMessagerBase::DrawShape();
}
};
class MobileMessagerPerfect : public MobileMessagerBase
{
virtual void Login(string usrname, string password)
{
MobileMessagerBase::PlaySound();
MobileMessagerBase::Connect();
cout << "MobileMessagerBase " << usrname << "Login IN" << endl;
}
virtual void SendMessage(string message)
{
MobileMessagerBase::PlaySound();
MobileMessagerBase::WriteText();
cout << "MobileMessagerBase message is " << message << " " << endl;
}
virtual void SendPicture(string image)
{
MobileMessagerBase::PlaySound();
MobileMessagerBase::DrawShape();
}
};
void Process()
{
Messager * m = new MobileMessagerPerfect(); //调用方式
}
然后我把对应的类图给画了出来:
明显发现,在继续发展一样会出现类爆炸现象,而且明显可以发现使用的继承函数相同,重复性太多。
如何解决这个问题呢,一般尝试继承时候,通过变成组合的形式来处理,这样可以对应减少代码量。我们也可以明显发现pc 与 Moblie 很多都是调用父类,其实就是重复构建。于是我们采用用父类创建时候才知道对应的,不就可以了吗
对应代码:
#pragma once
#include "stdafx.h"
//桥模式的单一职责模式
class MessagerImp {
public:
MessagerImp()
{
}
virtual void PlaySound() = 0;
virtual void DrawShape() = 0;
virtual void WriteText() = 0;
virtual void Connect() = 0;
virtual ~MessagerImp() {}
};
class Messager {
protected:
MessagerImp *messagerImp; //...
public:
Messager(MessagerImp * msg) {
this->messagerImp = msg;
}
virtual void Login(string usrname, string password) = 0;
virtual void SendMessage(string message) = 0;
virtual void SendPicture(string image) = 0;
virtual ~Messager() {}
};
//平台实现
class PCMessagerImp : public MessagerImp {
public:
PCMessagerImp()
{
}
virtual void PlaySound()
{
cout << "PCMessagerImp PlaySound " << endl;
}
virtual void DrawShape()
{
cout << "PCMessagerImp DrawShape " << endl;
}
virtual void WriteText()
{
cout << "PCMessagerImp WriteText " << endl;
}
virtual void Connect()
{
cout << "PCMessagerImp Connect " << endl;
}
};
class MobileMessagerImp : public MessagerImp {
public:
MobileMessagerImp()
{
}
virtual void PlaySound()
{
cout << "MobileMessagerImp PlaySound " << endl;
}
virtual void DrawShape()
{
cout << "MobileMessagerImp DrawShape " << endl;
}
virtual void WriteText()
{
cout << "MobileMessagerImp WriteText " << endl;
}
virtual void Connect()
{
cout << "MobileMessagerImp Connect " << endl;
}
};
//实现过程 业务方式
class MessagerLite : public Messager
{
public:
MessagerLite(MessagerImp * msg):Messager(msg)
{
}
virtual void Login(string usrname, string password)
{
messagerImp->Connect();
cout << "MessagerLite " << usrname << "Login IN" << endl;
}
virtual void SendMessage(string message)
{
messagerImp->WriteText();
cout << "MessagerLite message is " << message << " " << endl;
}
virtual void SendPicture(string image)
{
messagerImp->DrawShape();
}
};
class MessagerPerfect : public Messager
{
public:
MessagerPerfect(MessagerImp * msg) : Messager(msg)
{
}
virtual void Login(string usrname, string password)
{
messagerImp->PlaySound();
messagerImp->Connect();
cout << "MessagerPerfect " << usrname << "Login IN" << endl;
}
virtual void SendMessage(string message)
{
messagerImp->PlaySound();
messagerImp->WriteText();
cout << "MessagerPerfect message is " << message << " " << endl;
}
virtual void SendPicture(string image)
{
messagerImp->PlaySound();
messagerImp->DrawShape();
}
};
void process()
{
//将来创建
MessagerImp * messagerImp = new PCMessagerImp();
Messager * message = new MessagerPerfect(messagerImp);
message->Login("比卡丘不皮", "123456");
}
这里提示下大家,视频中李老师把:
Messager * message = new MessagerPerfect(messagerImp);
写成了:
Messager * message = new Messager(messagerImp);
这也是一个笔误,调用的时候要调用具体实现。对应的类图我也画出来了.
这样在我们不变化的就是Messager 与 MessagerImp 。实现了单一原则,然后在平台分开写,这样的调用就显得十分明了。这里最好的就是把继承变成了组合关系,这样设计防止了多子类的问题。
变化的部分就是对应实现,基础设计后就就解决了子类的爆炸问题。这就是桥模式。