C++设计模式之外观模式(一)

    自己有过组装电脑的人都知道,需要到电子市场去购买CPU、主板、硬盘、内存、显示器、光驱等配件。这个方案是好,但需要对各种配件都比较熟悉,这样才能选择最合适的配件,而且还需要考虑配件之间的兼容性。还有一个方案,就是到电子城,找一家专门组装电脑的公司,把自己的要求提出来,然后等着提电脑就好了。我们不需要关心要购买什么样的配件,也不需要知道电脑是如何组装起来的,所有这些操作都交给电脑组装公司,由它代为完成。在设计模式中,也存在一种类似的模式,完成某个功能需要调用其它多个模块,由外观类去调用这些模块来完成功能,这样客户端就不用跟系统中的多个模块交互,也不用知道那么多模块的细节了,称之为外观模式。

1、外观模式概述

    在软件开发中,有时候为了完成一项较为复杂的功能,一个客户类需要和多个业务类交互,而这些需要交互的业务类经常会作为一个整体出现,由于涉及到的类比较多,导致使用时代码较为复杂,此时,特别需要一个类似电脑组装公司一样的角色,由它来负责和多个业务类进行交互,而客户类只需与该类交互。外观模式通过引入一个新的外观类(Facade)来实现该功能,外观类充当了软件系统中的“电脑组装公司”,它为多个业务类的调用提供了一个统一的入口,简化了类与类之间的交互。在外观模式中,那些需要交互的业务类被称为子系统(Subsystem)。如果没有外观类,那么每个客户类需要和多个子系统之间进行复杂的交互,系统的耦合度将很大,而引入外观类之后,客户类只需要直接与外观类交互,客户类与子系统之间原有的复杂引用关系由外观类来实现,从而降低了系统的耦合度。

外观模式示意图

外观模式:为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

    外观类将客户类与子系统的内部复杂性分隔开,使得客户类只需要与外观角色打交道,而不需要与子系统内部的很多对象打交道。它是一种对象结构型模式。外观模式是迪米特法则的一种具体实现,通过引入一个新的外观角色可以降低原有系统的复杂度,同时降低客户类与子系统的耦合度。

外观模式结构图

    Facade(外观角色):在客户端可以调用它的方法,在外观角色中可以知道相关的(一个或者多个)子系统的功能和责任;在正常情况下,它将所有从客户端发来的请求委派到相应的子系统去,传递给相应的子系统对象处理。外观角色只负责委派操作,而不参与子系统的业务逻辑,为什么呢?因此外观对象只是提供一个访问子系统的一个路径而已,它不应该也不能参与具体的业务逻辑,违背了"单一原则",导致外观对象既负责业务处理,也负责委托操作。

    SubSystem(子系统角色):在软件系统中可以有一个或者多个子系统角色,每一个子系统可以不是一个单独的类,而是一个类的集合,它实现子系统的功能;每一个子系统都可以被客户端直接调用,或者被外观角色调用,它处理由外观类传过来的请求;子系统并不知道外观的存在,对于子系统而言,外观角色仅仅是另外一个客户端而已。

    外观模式的主要目的在于降低系统的复杂程度,在面向对象软件系统中,类与类之间的关系越多,不能表示系统设计得越好,反而表示系统中类之间的耦合度太大,这样的系统在维护和修改时都缺乏灵活性,因为一个类的改动会导致多个类发生变化,而外观模式的引入在很大程度上降低了类与类之间的耦合关系。引入外观模式之后,增加新的子系统或者移除子系统都非常方便,客户类无须进行修改(或者极少的修改),只需要在外观类中增加或移除对子系统的引用即可。从这一点来说,外观模式在一定程度上并不符合开闭原则,增加新的子系统需要对原有系统进行一定的修改,虽然这个修改工作量不大。

    外观模式中所指的子系统是一个广义的概念,它可以是一个类、一个功能模块、系统的一个组成部分或者一个完整的系统。子系统类通常是一些业务类,实现了一些具体的、独立的业务功能,其典型代码如下:

//子系统A
class SubSystemA
{
public:
	void MethodA()
	{
		//业务实现代码
	}
};


//子系统B
class SubSystemB
{
public:
	void MethodB()
	{
		//业务实现代码
	}
};


//子系统C
class SubSystemC
{
public:
	void MethodC()
	{
		//业务实现代码
	}
};

    在引入外观类之后,与子系统业务类之间的交互统一由外观类来完成,在外观类中通常存在如下代码:

//外观类
class Facade
{
private:
	//维持子系统的引用
	SubSystemA * m_pSubSystemA;
	SubSystemB * m_pSubSystemB;
	SubSystemC * m_pSubSystemC;
public:
	//创建各子系统对象
	Facade()
	{
		m_pSubSystemA = new SubSystemA();
		m_pSubSystemB = new SubSystemB();
		m_pSubSystemC = new SubSystemC();
	}

	//销毁子系统对象
	~Facade()
	{
		delete m_pSubSystemA;
		m_pSubSystemA = NULL;

		delete m_pSubSystemB;
		m_pSubSystemB = NULL;

		delete m_pSubSystemC;
		m_pSubSystemC = NULL;
	}

	//委派操作
	void Method()
	{
		m_pSubSystemA->MethodA();
		m_pSubSystemB->MethodB();
		m_pSubSystemC->MethodC();
	}
};
    由于在外观类中维持了对子系统对象的引用,客户端可以通过外观类来间接调用子系统对象的业务方法,而无须与子系统对象直接交互。引入外观类后,客户端代码变得非常简单,典型代码如下:

int main()
{
	Facade * pFacade = new Facade()

	pFacade->Method();

	delete pFacade;
	pFacade = NULL;
}




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值