外观模式:要求一个子系统与外部通信必须通过一个同一的系统完成,也就是把一系列的子系统封装在一个同一的大系统中。子系统中的所有调用行为都是通过大系统提供同一的接口来完成。
在一个绘图系统中,需要绘制各种这样的图形,比如说是矩形、圆形、直线等。那好我们就根据以上场景搭建一个简单的绘制场景。首先把各种绘制的图形定义出来。
矩形:
//矩形
class MyRectangle {
public:
MyRectangle(int w,int h);
voID draw();
private:
int _wIDth,_height;
};
MyRectangle::MyRectangle(int w,int h) {
_wIDth = w;
_height = h;
}
voID MyRectangle::draw() {
printf("绘制矩形 - 长:%d 宽:%dn",_wIDth,_height);
}
圆形:
//圆
class MyCircle {
public:
MyCircle(int centerX,int centerY,int radio);
voID draw();
private:
int _centerX,_centerY,_radio;
};
MyCircle::MyCircle(int centerX,int radio) {
_centerX = centerX;
_centerY = centerY;
_radio = radio;
}
voID MyCircle::draw() {
printf("绘制圆 - 圆心:(%d,%d) 半径:%dn",_centerX,_radio);
}
直线:
//直线
class Myline {
public:
Myline(int firstX,int firstY,int secondX,int secondY);
voID draw();
private:
int _firstX,_firstY,_secondX,_secondY;
};
Myline::Myline(int firstX,int secondY) {
_firstX = firstX;
_firstY = firstY;
_secondX = secondX;
_secondY = secondY;
}
voID Myline::draw() {
printf("绘制直线 - 起点:(%d,%d),终点:(%d,%d)n",_firstX,_secondY);
}
点:
//点
class MyPoint {
public:
MyPoint(int x,int y);
voID draw();
private:
int _x,_y;
};
MyPoint::MyPoint(int x,int y) {
_x = x;
_y = y;
}
voID MyPoint::draw() {
printf("绘制点 - 坐标:(%d,_x,_y);
}
以上需要绘制的图形已经添加完成了,下面看一下客户端是如何调用的:
int main() {
//绘制点
MyPoint* pt = new MyPoint(10,20);
pt->draw();
//绘制直线
Myline* l = new Myline(30,30,90,95);
l->draw();
//绘制矩形
MyRectangle* rect = new MyRectangle(150,300);
rect->draw();
//绘制圆
MyCircle* circle = new MyCircle(100,100,50);
circle->draw();
return 0;
}
代码编写完成了,运行一下:
OK,调用完成了,看到了吗?
也就是说我每次添加一个绘制的图形都要重写一遍客户端,如果添加的图形比较复杂的,或者是有很多组合图形的情况,客户端就会变得非常的臃肿,不易于维护。
那么怎么解决的?咱们把需要绘制的这个部分功能重新封装起来。需要重新定义一个类实现这个功能。
class MyDraw {
public:
MyDraw();
voID init();
voID draw();
private:
MyRectangle* _myRect;
MyCircle* _myCircle;
Myline* _myline;
MyPoint* _myPoint;
};
MyDraw::MyDraw() {
}
voID MyDraw::init() {
_myPoint = new MyPoint(10,20);
_myline = new Myline(30,95);
_myRect = new MyRectangle(150,300);
_myCircle = new MyCircle(100,50);
}
voID MyDraw::draw() {
_myPoint->draw();
_myline->draw();
_myRect->draw();
_myCircle->draw();
}
现在把客户端的调用之后修改一下:
int main() {
MyDraw* myDraw = new MyDraw;
myDraw->init();
myDraw->draw();
return 0;
}
运行一下:
嗯哼,运行效果是一样的。
客户端只要编写很少的代码就可以实现上述的功能,也许你会说,这有什么区别嘛?只不过把我需要的功能重新封装了一下而已呀。
但是你不要忘了,如果直接使用的话,各种绘制图形就会和客户端产生一定的耦合性,如果是客户端做了修改就会影响到这部分的修改,但是如果做了封装的话就是把客户端和实际的绘制过程分开来,互不影响。
每次需要绘制的时候,只要把封装的接口直接调用就可以了。
其次,如果想要添加新的绘制图形,比如说三角形、图片等,只要在封装的类中添加行的绘制就可以了,而不用修改客户端的代码。
再次,如果这部分绘制的过程是通过DLL形式发布出去的,那么每次只要修改DLL中代码之后重新编译就可以了,和客户端没有什么关系,客户端没有修改任何代码就能实现的添加新的绘制图形。
看看咱们的代码是不是还有优化的空间?
既然会都有绘制的功能,是不是可以把绘制的过程提取出来形成基类呢?
class IDraw {
public:
IDraw();
~IDraw();
virtual voID draw();
};
IDraw::IDraw() {
}
IDraw::~IDraw() {
}
voID IDraw::draw() {
}
绘制相关的类都继承这个基类:
//矩形
class MyRectangle:public IDraw {
public:
MyRectangle(int w,int h);
voID draw()overrIDe;
private:
int _wIDth,_height;
};
//圆
class MyCircle :public IDraw {
public:
MyCircle(int centerX,int radio);
voID draw()overrIDe;
private:
int _centerX,_radio;
};
//直线
class Myline :public IDraw {
public:
Myline(int firstX,int secondY);
voID draw()overrIDe;
private:
int _firstX,_secondY;
};
//点
class MyPoint :public IDraw {
public:
MyPoint(int x,int y);
voID draw()overrIDe;
private:
int _x,_y;
};
CPP文件保持不变,这里就不在重复了。
然后在修改一下绘制类:
class MyDraw {
public:
MyDraw();
voID init();
voID draw();
private:
std::vector
};
MyDraw::MyDraw() {
}
voID MyDraw::init() {
_drawObJs.push_back(new MyPoint(10,20));
_drawObJs.push_back(new Myline(30,95));
_drawObJs.push_back(new MyRectangle(150,300));
_drawObJs.push_back(new MyCircle(100,50));
}
voID MyDraw::draw() {
int cnt = _drawObJs.size();
for (int i = 0; i < cnt;i++){
_drawObJs.at(i)->draw();
}
}
这样是不是更加方便了,客户端都有不用做任何的修改!
如果要添加新的图形,只要是继承IDraw这个基类,然后在子类中完成绘制功能,把生成的子类对象,添加到_drawObJs中就可以了。绘制这部分功能就会自动的调用完成了。
外观模式优点:
1.减少了系统之间的耦合性。
2.提高灵活性。
总结以上是内存溢出为你收集整理的C++设计模式-外观模式详解全部内容,希望文章能够帮你解决C++设计模式-外观模式详解所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)