1、系统的复杂度

需求:开发一个坦克模拟系统用于模拟坦克车在各种作战环境中的行为,其中坦克系统由引擎、控制器、车轮等各子系统构成.然后由对应的子系统调用.

常规的设计如下:

        #region 坦克系统组成
/// <summary>
/// 引擎类
/// </summary>
public class Engine
{
public void EngineActionA() { } public void EngineActionB() { }
} /// <summary>
/// 车轮
/// </summary>
public class Wheel
{
public void WheelActionA() { } public void WheelActionB() { }
} /// <summary>
/// 控制器
/// </summary>
public class Controller
{
public void ControllerActionA() { } public void COntrollerActionB() { }
}
#endregion /// <summary>
/// 游戏系统
/// </summary>
public class GameSystem
{
/// <summary>
/// 引擎初始化类
/// </summary>
public class EngineInit
{
/// <summary>
/// 引擎初始化,并将控制权交给控制器
/// </summary>
public void Init()
{
var engine = new Engine();
var controller = new Controller();
}
} /// <summary>
/// 车轮初始化类
/// </summary>
public class WheelInit
{
/// <summary>
/// 车轮初始化,并将控制权交给控制器
/// </summary>
public void Init()
{
var engine = new Wheel();
var controller = new Controller();
}
}
}

ok,这是最简单的实现,完成了游戏系统对坦克系统的调用,将上面的系统调用抽象成一张构成图,如下:

可以发现,坦克系统的各个组成部分,柔和到了游戏系统的各个类型中,这种设计一旦坦克的组成部分发生变化,所造成的维护成本是十分昂贵的!

2、问题

组件(坦克系统)的客户端调用程序(系统系统)和组件中各种复杂的子系统之间产生了过多的耦合,随着外部客户程序和组件各子系统的演化,这种耦合产生的维护成本十分昂贵.

3、解决方案

必须抽象出一层接口,这层接口需要将坦克系统进行抽象,并告诉游戏客户端哪些功能,是它可以调用的,而不是让系统系统自己去调用坦克系统的组件来实现相关的功能,将组件系统(坦克系统)和外部调用客户程序(游戏系统)的变化之间的依赖解耦.将这种变化成本交给这层接口来承担.

        #region 坦克系统组成
/// <summary>
/// 引擎类
/// </summary>
internal class Engine
{
public void EngineActionA() { } public void EngineActionB() { }
} /// <summary>
/// 车轮
/// </summary>
internal class Wheel
{
public void WheelActionA() { } public void WheelActionB() { }
} /// <summary>
/// 控制器
/// </summary>
internal class Controller
{
public void ControllerActionA() { } public void COntrollerActionB() { }
}
#endregion public class TankFacade
{
//注入相关坦克系统的组件,如果引擎、车轮这些可能会有风格的变化,可以考虑使用工厂模式来实现注入
Engine[] Engines = new Engine[];
Wheel[] Wheels = new Wheel[];
Controller Controller = new Controller(); /// <summary>
/// 坦克的启动功能,完成引擎、控制器的初始化.
/// </summary>
public void Start()
{ } /// <summary>
/// 坦克的停止功能,完成引擎、控制器的停止
/// </summary>
public void Stop()
{ }
}

客户端调用代码如下:

        /// <summary>
/// 游戏系统
/// </summary>
public class GameSystem
{
private TankFacade tankFacade = null;
/// <summary>
/// 开始游戏
/// </summary>
public void Run()
{
TankFacade facade = new TankFacade();
facade.Start();
} /// <summary>
/// 结束游戏
/// </summary>
public void Stop()
{
if(tankFacade!=null)
tankFacade.Stop();
throw new Exception("引擎未启动,无法停止!");
}
}

通过TankFacade类,将坦克系统的组件集成到里面,提供给游戏系统它所需要的功能,很好的实现了客户端调用系统依赖与坦克组件的问题,完成了解耦.解耦后的结构图如下:

4、要点

(1)、从客户程序的角度来看,Facade模式补不仅简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,达到了一种解耦的效果,内部子系统的变化不会影响到Facade接口的变化.

(2)、Facade模式更注重从架构的层次去看待整个系统,而不是单个类的层次,更多的时候是一种架构设计模式.

(3)、Facede模式与Apater模式、Bridge模式、Decorator模式的区别,Facede模式注重简化接口,Apater注重转换接口(将现有接口转换成客户需要的接口),Bridge模式接口的分离(即系统按照两个维度及以上的变化适合使用Bridge模式),Decorator模式注重稳定接口的情况下,为接口扩展功能.

Facade外观模式(结构性模式)的更多相关文章

  1. php设计模式之Proxy(代理模式)和Facade(外观)设计模式

    Proxy(代理模式)和Facade(外观)设计模式它们均为更复杂的功能提供抽象化的概念,但这两种实现抽象化的过程大不相同 Proxy案例中,所有的方法和成员变量都来自于目标对象,必要时,该代理能够对 ...

  2. (转载)设计模式学习笔记(十一)——Facade外观模式

    (转载)http://www.cnblogs.com/kid-li/archive/2006/07/10/446904.html Facade外观模式,是一种结构型模式,它主要解决的问题是:组件的客户 ...

  3. 设计模式(十一):FACADE外观模式 -- 结构型模式

    1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性.例子1:一个电源总开关可以控制四盏灯.一个风扇 ...

  4. 外观模式 门面模式 Facade 结构型 设计模式(十三)

    外观模式(FACADE) 又称为门面模式   意图 为子系统中的一组接口提供一个一致的界面 Facade模式定义了一个高层接口,这一接口使得这一子系统更加易于使用. 意图解析 随着项目的持续发展,系统 ...

  5. NET设计模式 第二部分 结构性模式(11):外观模式(Façade Pattern)

    外观模式(Façade Pattern) ——.NET设计模式系列之十二 Terrylee,2006年3月 概述 在软件开发系统中,客户程序经常会与复杂系统的内部子系统之间产生耦合,而导致客户程序随着 ...

  6. Facade - 外观模式

    1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性.例子1:一个电源总开关可以控制四盏灯.一个风扇 ...

  7. 设计模式10: Facade 外观模式(结构型模式)

    Facade 外观模式(结构型模式) 系统的复杂度 假设我们要开发一个坦克模式系统用于模拟坦克车在各种作战环境中的行为,其中坦克系统由引擎.控制器.车轮.车身等各个子系统构成. internal cl ...

  8. Facade——外观模式

    Facade外观模式,也是比较常用的一种模式,基本上所有软件系统中都会用到. GOF 在<设计模式>一书中给出如下定义:为子系统中的一组接口提供一个一致的界面, Facade 模式定义了一 ...

  9. 设计模式在实际业务应用中的介绍之3——外观或门面模式Facade对AOP装配业务工厂的应用

    在C#中实现的基于外观或门面模式打造的业务应用案例 以前一直没有想过写一些东西来把项目中用到的知识点及技术实现做一个归纳整理并分享出来.现在打算逐渐的把项目中的一些东西整理并分享出来,与大家共勉! 外 ...

随机推荐

  1. Day1-Python基础--数据类型

    距离上次更新,已经一月有余.说明学习状态不好,且滞后严重.第二模块也滞后5周之多,可能学习方法不对,有点凌乱,导致写作业时思路还是打不开,再一个是练习的太少了吧,以后得多挤挤时间来了.目前到了这个年纪 ...

  2. poj 3278 Catch That Cow(bfs+队列)

    Description Farmer John has been informed of the location of a fugitive cow and wants to catch her i ...

  3. volatile 实现 单例模式

    单例模式的一种实现方式,但很多人会忽略volatile关键字,因为没有该关键字,程序也可以很好的运行,只不过代码的稳定性总不是100%,说不定在未来的某个时刻,隐藏的bug就出来了. 双重校验锁 cl ...

  4. app.json

    APP.JSON 文件来对微信小程序进行全局配置,决定页面文件的路径.窗口表现.设置网络超时时间.设置多 TAB 等.相当于iOS开发中的AppDelegate 注意该文件不可添加任何注释. {   ...

  5. (转)MVC语法-基础

    好久没有关注微软的开发了,今天看到了MVC3,顺便学习学习,我觉得Razor是个不错的做法,比使用<%%>简单多了,而且好看.首先“_”开头的cshtml文档将不能在服务器上访问,和asp ...

  6. 20155326 2016-2017-2 《Java程序设计》第九周学习总结

    20155326 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 1.撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找. 2.JDBC目的 ...

  7. Android webview 退出时关闭声音 4.视频全屏 添加cookie

    全屏问题,可以参考 http://bbs.csdn.net/topics/390839259,点击 webView = (WebView) findViewById(R.id.webView); vi ...

  8. STL容器(C11)--unordered_map用法

    http://www.cplusplus.com/reference/unordered_map/unordered_map/

  9. (使用STL自带的排序功能进行排序7.3.2)POJ 2092 Grandpa is Famous(结构体排序)

    /* * POJ_2092.cpp * * Created on: 2013年11月1日 * Author: Administrator */ #include <iostream> #i ...

  10. 关于国密算法 SM1,SM2,SM3,SM4 的笔记

    国密即国家密码局认定的国产密码算法.主要有SM1,SM2,SM3,SM4.密钥长度和分组长度均为128位. SM1 为对称加密.其加密强度与AES相当.该算法不公开,调用该算法时,需要通过加密芯片的接 ...