首页 > 分享 > 外观模式解析

外观模式解析

外观模式还是相当普遍的,先来看看几个例子:

1. 一台电脑有很多东西组成,包括硬件,软件。硬件又包含主板,CPU,内存什么的,软件又包含操作系统,操作系统里面又有一大堆非常复杂的驱动,各个驱动之间又有很多关系。那么我们怎么启动这么复杂的一个东西呢?我们所要做的就是按一下电源开关。当用户按下电源开关后,操作系统会把电脑运行起来,中间过程那是相当的复杂。对于用户来说,电源开关就是一个简单使用的接口,是一个facade。如果我们想进入安全模式,OK,在启动过程中按一下F8,那么这是另外一个facade,F8会调用一系列子系统来进入安全模式。

2. 一个手机有很多东西组成,那么怎么启动手机呢?也就是按一下电源。

3. 现在的汽车大多数都是手自一体的,那么自动档就是一个FACADE,通过自动档系统,用户根本就无需知道怎么时候挂1档,什么时候挂5档。当然对于那些有需求的驾驶员来说,他可以使用手动档(子系统)。

通过以上几个例子,我们基本可以知道外观模式(FACADE)其实就是给子系统包装一下,然后提供一个简单的接口让用户可以比较容易的使用。

GOF设计模式中是这么定义的:

意图

为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

结构图

上面的结构图,我们假设有一个子系统,子系统里面有很多子部件,子部件之间有很多耦合关系,那么如果让用户来调用这些子系统也不是不可以,但是可能会比较麻烦,或者让一个对子系统架构不熟悉的程序员来调用的话,还可能出现错误。如果我们可以提供一个facade类,这个facade会把子系统包装起来,然后里面提供一个Run函数,用户只需要调用Facade的Run就可以了,这就隐藏了子系统的调用过程,对于客户来说减少了大量的工作。

这里举一个非常简单的例子,我们还是继续沿用Composite和Decorator里面用过的例子。这次我们假设我们有一个子系统,这个子系统可以画直线,画正方形,画照片。子系统包括:CLine,CRect和CPhoto。其中CRect耦合了CLine,也就是说CRect是用CLine画出来的。子系统结构如下:

假如我们现在要画一个带框的照片(就是一个正方形,里面有个照片),该怎么画呢?可以这么做:

CLine* line = new CLine();

CRect* rect = new CRect(line);

CPhoto* photo = new CPhoto();

rect->Draw();

photo->Draw();

delete rect;

delete photo;

先生成一个CLine对象,然后传给CRect对象,再生成一个CPhone对象,然后按照顺序调用CRect的Draw()和CPhone的Draw()。

没有问题,我成功地画了一个正方形,然后正方形里面有个照片。但是这里有个问题:假如我们的程序员对这套子系统不熟悉怎么办呢?他得先学习一下这套子系统,包括子系统里面的子部件的关系,然后他才能正确地画出带框照片。如果我们在这套子系统的基础上提供一个Facade,会不会好点呢?给出代码:

#pragma once

#include <iostream>

class CGraphic

{

public:

virtual void Draw() = 0;

};

class CLine: public CGraphic

{

public:

virtual void Draw()

{

std::cout << "Draw linen";

}

};

class CRect: public CGraphic

{

public:

CRect(CLine* line): _line(line)

{

}

virtual ~CRect()

{

if (_line)

{

delete _line;

_line = NULL;

}

}

virtual void Draw()

{

_line->Draw();

std::cout << "Draw rectn";

}

protected:

CLine* _line;

};

class CPhoto: public CGraphic

{

public:

void Draw()

{

std::cout << "draw picturen";

}

};

class CBorderPhotoFacade

{

public:

static CBorderPhotoFacade* GetInst()

{

static CBorderPhotoFacade facade;

return &facade;

}

virtual void DrawPhoto()

{

CLine* line = new CLine();

CRect* rect = new CRect(line);

CPhoto* photo = new CPhoto();

rect->Draw();

photo->Draw();

delete rect;

delete photo;

}

protected:

CBorderPhotoFacade()

{

}

};

上面的代码中,CGraphic,CLine,CRect,CPhoto共同组成了一个子系统。然后CBorderPhotoFacade是一个外观类,里面就提供了一个函数DrawPhoto(),这个函数会画出一个带框照片。那么客户端就可以这么调用:

CBorderPhotoFacade::GetInst()->DrawPhoto();

跟前面的版本相比较,从客户端的角度来讲,就是用CBorderPhotoFacade::DrawPhoto()代替了之前一系列子系统类的调用。也就是说,我们通过CBorderPhotoFacade类提供了一个高层接口,使得用户只需要调用这个高层接口,而无需去调用复杂的子系统。这个就是Facade模式的作用。
 

 优点:

1. 它对客户屏蔽子系统组件,因而减少了客户处理的对象的数目使得子系统使用起来更加方便。上面的例子里面,客户端根本无需知道CLine,CRect,CPhoto,直接调用CBorderPhotoFacade就可以了。

2. 它实现了子系统和客户之间的松耦合关系;

3. 如果应用需要,客户还可以继续使用子系统。Facade只是提供一个高层接口,如果高层接口不能满足客户需要,那么直接调用子系统就是了。

进阶:

例子里面我们只是提供了一个Facade类,那么当我们需要提供多个Facade的时候,我们可以给Facade提供一个接口,然后子类化Facade。这样更灵活,当然付出的代价也大了,因为需要多增加几个类。或者我们可以给Facade类增加一个参数factory,然后把子系统对象的创建放到factory里面,也就是引入抽象工厂模式。这些都视情况而定,如果子系统比较复杂,那么就可以考虑Facade子类化或者直接引入抽象工厂类等等。

另外,通常来讲,Facade都是单例对象。我们的例子里面也把Facade类做成了单例类。

相关知识

深入解析,花店经营之道,揭秘最赚钱的业务模式与策略
豹纹鲨是几级保护动物?全面解析独特的外观与生物习性 —【发财农业网】
花海景观设计之全面解析
'紫荆是啥:科、药、花、树,全解析'
水肥一体化多种技术模式解析
探秘猴头手串的秘密——以什么植物的种子为主?(从外观、产地、用途到文化意义,一一解析)
网店店铺运营模式解析(什么是网店店铺运营模式)
全面对比:蓝田玉与菜花玉的区别,高清图鉴解析
花卉旅游如何盈利?这六大经典模式解析,帮你理清思路!
2020高考地理刷题1+1(2019模拟题)讲练练习:重组卷(九)【解析】

网址: 外观模式解析 https://m.huajiangbk.com/newsview1235726.html

所属分类:花卉
上一篇: 将长方形纸条折成如图形状,BC为
下一篇: 用同种材料制成的质量均为M=1k