设计模式学习笔记十三:外观模式(Facade Pattern)
 

     1.概述
     外观模式(Façade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层的接口,这个接口使得这个子系统更加容易使用。通过这个接口,其他系统可以方便的调用子系统中的功能,而忽略子系统内部发生的变化。
     外观模式(Façade)是经常使用的模式之一,并且可以应用在任何层次和粒度的应用中,小到API的封装,大到封装整个系统。例如在使用ADO.NET时,为了执行SQL,需要使用Connection,Command和DataAdapter等,这样显然比较的麻烦,因此我们可以将整个数据库访问封装到一个类中,该类封装了访问数据库的过程,这个类就是一个外观模式。
     下面我们看外观模式的结构:

设计模式学习笔记十三:外观模式(Facade Pattern)_编程

 

     结构图说明:

     外观类(Facade):客户端可以调用这个类的方法。此类知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本类会将所有从客户端发来的请求委派到相应的子系统去。

子系统(subsystem):可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被外观类调用。子系统并不知道门面的存在,对于子系统而言,外观类仅仅是另外一个客户端而已。

     基本代码:(来自大话设计模式)

     四个子系统类:

设计模式学习笔记十三:外观模式(Facade Pattern)_编程_02
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03    public class SubSystemOne
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_04    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public void MethodOne()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            Console.WriteLine(" 子系统方法一");
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_09    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03    public class SubSystemTwo
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_04    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public void MethodTwo()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            Console.WriteLine(" 子系统方法二");
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_09    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03    public class SubSystemThree
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_04    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public void MethodThree()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            Console.WriteLine(" 子系统方法三");
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_09    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03    public class SubSystemFour
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_04    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public void MethodFour()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            Console.WriteLine(" 子系统方法四");
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_09    }

     外观类:

设计模式学习笔记十三:外观模式(Facade Pattern)_编程_02
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03    public class Facade
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_04    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        SubSystemOne one;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        SubSystemTwo two;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        SubSystemThree three;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        SubSystemFour four;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public Facade()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            one = new SubSystemOne();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            two = new SubSystemTwo();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            three = new SubSystemThree();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            four = new SubSystemFour();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public void MethodA()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            Console.WriteLine("\n方法组A() ---- ");
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            one.MethodOne();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            two.MethodTwo();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            four.MethodFour();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public void MethodB()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            Console.WriteLine("\n方法组B() ---- ");
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            two.MethodTwo();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            three.MethodThree();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_09    }

     客户端调用(由于Facade的作用,客户端可以根本不知道四个子系统类的存在):

设计模式学习笔记十三:外观模式(Facade Pattern)_编程_02
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03    public class Program
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_04    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        static void Main(string[] args)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            Facade facade = new Facade();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            facade.MethodA();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            facade.MethodB();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            Console.Read();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_09    }

     2.实例

     数据库访问外观模式:

     在使用ADO.NET访问数据库时,我们通常需要编写下面的访问数据库的语句来访问数据库:

设计模式学习笔记十三:外观模式(Facade Pattern)_编程_02
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03            SqlConnection myConn = new SqlConnection();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03            myConn.ConnectionString = "Database=xxx;Server=local;User Id=sa;Password=123456;";
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03            myConn.Open();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03            DataTable dt = new DataTable();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03            SqlCommand cmd = new SqlCommand(strSQL);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03            SqlDataAdapter da = new SqlDataAdapter(cmd);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03            cmd.Connection = myConn;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03            da.Fill(dt);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03            myConn.Close();

     如上面的代码所示,为了执行一个SQL,需要使用Connection、Command和DataAdapter,这样显然比较麻烦,因此,我们可以利用外观模式,将数据库访问封装到一个类中,该类分装了访问数据库的过程。下面是给出一个通用的封装的数据访问层,代码如下:

 

设计模式学习笔记十三:外观模式(Facade Pattern)_编程_02
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03using System;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03using System.Data;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03using System.Collections;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03namespace DAL
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_04{
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06    /// <summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05    /// DALResult 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05    /// Copyright peida 2008-7-15
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08    /// </summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05    public class DALResult
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public bool IsSucceed;            //存储过程是否执行成功
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public string errorMessage;        //访问数据库失败
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public int rowsCount;            //结果集行数.
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public object theFirst;            //第一行第一列
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public Hashtable OutputValues;    //存储过程output值,放在(HashTable)表OutputValues里.        
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public DataTable datatable;        //存储过程返回的结果集,放在(DataTable)表datatable里.
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public DataSet dataSet;            //存储过程返回的结果集,放在DataSet表中
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public DALResult()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            IsSucceed = false;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            rowsCount = 0;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            errorMessage = "";
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            theFirst = null;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            OutputValues = new Hashtable();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            datatable=new DataTable();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            dataSet=new DataSet();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_09}

      SQL语句的分装:

设计模式学习笔记十三:外观模式(Facade Pattern)_编程_02
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03using System;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03using System.IO;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03using System.Data;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03using System.Data.SqlClient;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03using System.Configuration;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03using System.Collections;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03namespace DAL
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_04{
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06    /// <summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05    /// SQL_Base 调用SQL语句
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05    /// Copyright peida 2008-7-15
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08    /// </summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05    public class SQL_Base : IDisposable
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                private string strconn = "";
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public SQL_Base() : this("")
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            strconn = ConfigurationSettings.AppSettings["DBpath"];
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        //重载
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public SQL_Base(string sql_name)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            strconn = ConfigurationSettings.AppSettings[sql_name];
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        //私有成员变量
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        private string sql_name;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        private SqlConnection myConnection;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        private SqlCommand myCommand;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        //公共属性
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public string SQLName
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            get
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06            { 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                return this.sql_name; 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08            }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            set
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06            { 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                this.sql_name = value; 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08            }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        /// <summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        /// 执行SQL语句,返回数据集:DataTable或DataSet
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        /// </summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        /// <returns>返回DALResult</returns>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public DALResult ExecuteSqlData()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {            
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            DALResult result = new DALResult();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myConnection = new SqlConnection(strconn);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myCommand = new SqlCommand(this.sql_name, myConnection);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myCommand.CommandType = CommandType.Text;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            SqlDataAdapter myAdapter = new SqlDataAdapter(myCommand);    
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myConnection.Open();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            using(SqlTransaction trans  = myConnection.BeginTransaction())
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06            {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                try
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    if(trans!=null)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                        myCommand.Transaction = trans;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    //填充数据,将结果填充到DALResult集中
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myAdapter.Fill(result.dataSet);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    if(result.dataSet.Tables.Count>0)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                        result.datatable=result.dataSet.Tables[0].Copy();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                        if(result.dataSet.Tables[0].Rows.Count>0)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                            result.rowsCount = result.dataSet.Tables[0].Rows.Count;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    result.IsSucceed = true;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    //提交事物
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    trans.Commit();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                catch(Exception e)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    result.errorMessage = e.Message;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                //如果捕捉了异常,但仍会执行包括在 finally 块中的输出语句
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                finally
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                {                    
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myAdapter.Dispose();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myCommand.Dispose();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myConnection.Close();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myConnection.Dispose();                
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08            }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            return result;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        /// <summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        /// 获取第一行第一列数据
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        /// </summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        /// <returns>返回DALResult</returns>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public DALResult ExecuteSqlScalar()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            DALResult result = new DALResult();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myConnection = new SqlConnection(strconn);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myCommand = new SqlCommand(this.sql_name, myConnection);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myCommand.CommandType = CommandType.Text;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myConnection.Open();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            using(SqlTransaction trans  = myConnection.BeginTransaction())
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06            {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                try
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    if(trans!=null)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                        myCommand.Transaction = trans;                        
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    object scalarresult = myCommand.ExecuteScalar();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    if(Object.Equals(scalarresult,null))
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                        result.errorMessage = "没有取到数据";
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    else
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                        result.theFirst = scalarresult;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                        //取到数据
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                        result.rowsCount=1;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    result.IsSucceed = true;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    //提交事物
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    trans.Commit();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                catch(Exception e)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    result.errorMessage = e.Message;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                finally
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myCommand.Dispose();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myConnection.Close();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myConnection.Dispose();                
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08            }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            return result;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        /// <summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        /// 执行无返回结果的SQL语句
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        /// </summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        /// <returns>返回DALResult</returns>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public DALResult ExecuteSqlNonQuery()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            DALResult result = new DALResult();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myConnection = new SqlConnection(strconn);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myCommand = new SqlCommand(this.sql_name, myConnection);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myCommand.CommandType = CommandType.Text;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            myConnection.Open();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            using(SqlTransaction trans  = myConnection.BeginTransaction())
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06            {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                try
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    if(trans!=null)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                    {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                        myCommand.Transaction = trans;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myCommand.ExecuteNonQuery();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    result.IsSucceed = true;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    //提交事物
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    trans.Commit();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                catch(Exception e)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    result.errorMessage = e.Message;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                finally
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06                {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myCommand.Dispose();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myConnection.Close();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    myConnection.Dispose();                
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08                }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08            }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            return result;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        /// <summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        /// ExecuteReader
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        /// 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        /// </summary>
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        /// 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public SqlDataReader ExecuteReader(CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            SqlCommand cmd = new SqlCommand();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            SqlConnection conn = new SqlConnection(strconn);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            // we use a try/catch here because if the method throws an exception we want to 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            // close the connection throw code, because no datareader will exist, hence the 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            // commandBehaviour.CloseConnection will not work
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            try
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06            {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                cmd.Parameters.Clear();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                return rdr;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08            }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            catch
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06            {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                conn.Close();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                throw;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08            }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        private void PrepareCommand(SqlCommand cmd, SqlConnection conn, SqlTransaction trans, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            if (conn.State != ConnectionState.Open)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                conn.Open();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            cmd.Connection = conn;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            cmd.CommandText = cmdText;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            if (trans != null)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                cmd.Transaction = trans;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            cmd.CommandType = cmdType;
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            if (cmdParms != null)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06            {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                foreach (SqlParameter parm in cmdParms)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                    cmd.Parameters.Add(parm);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08            }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        public void Dispose()
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            Dispose(true);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            GC.SuppressFinalize(true);
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05        protected virtual void Dispose(bool disposing)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06        {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            if (! disposing)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                return; 
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05            if(myConnection != null)
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_06            {
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_05                myConnection.Dispose();
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08            }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08        }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_08    }
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_09}
设计模式学习笔记十三:外观模式(Facade Pattern)_编程_03

     存储过程的封装:

 

设计模式学习笔记十三:外观模式(Facade Pattern)_编程_02
using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace DAL
{
    /// <summary>
    ///调用存储过程
    ///Copyright Peida 2008-7-15
    /// </summary>
    public class SP_Base : IDisposable
    {
        public SP_Base() : this("")
        {
        }
        //重载
        public SP_Base(string sql_name)
        {
            this.sp_name = sp_name;
        }
        //私有成员变量
        private string strconn=ConfigurationSettings.AppSettings["DBpath"];
        private string sp_name; 
        private SqlConnection myConnection;
        private SqlCommand myCommand;
        //存储过程参数
        private SqlParameter myParameter;
        
        //公共属性
        public string ProcedureName
        {
            get
            { 
                return this.sp_name; 
            }
            set
            { 
                this.sp_name = value; 
            }
        }        

        //========begin=========
        /// <summary>
        /// 调用存储过程
        /// </summary>
        /// <param name="parameters">参数集合</param>
        /// <returns></returns>
        public  DALResult Call_SP(params object[] parameters)
        {
            DALResult result = new DALResult();
            myConnection  = new SqlConnection(strconn);            
            myCommand = new SqlCommand(this.ProcedureName, myConnection);
            myCommand.CommandType = CommandType.StoredProcedure;            
            SqlDataAdapter myAdapter = new SqlDataAdapter(myCommand);    

            myConnection.Open();
            GetProcedureParameter(result,parameters);
            //事物
            using(SqlTransaction trans = myConnection.BeginTransaction())
            {
                try
                {                    
                    if(trans!=null)
                    {
                        myCommand.Transaction = trans;
                    }
                    //填充数据,将结果填充到DALResult集中
                    myAdapter.Fill(result.dataSet);
                    if(result.dataSet.Tables.Count>0)
                    {
                        result.datatable=result.dataSet.Tables[0].Copy();
                        if(result.dataSet.Tables[0].Rows.Count>0)
                        {
                            result.rowsCount = result.dataSet.Tables[0].Rows.Count;
                        }
                    }
                    result.IsSucceed = true;                    
                                
                    //将输出参数的值添加到Result
                    GetOutputValue(result);
                    //提交事物
                    trans.Commit();
                }
                catch(Exception e)
                {
                    result.errorMessage = e.Message;
                    //事物回滚
                    trans.Rollback();
                }
                
                //如果捕捉了异常,但仍会执行包括在 finally 块中的输出语句
                finally
                {
                    myAdapter.Dispose();
                    myCommand.Dispose();
                    myConnection.Close();
                    myConnection.Dispose();
                }
            }
            return result;
        }

        /// <summary>
        /// 将参数添加到存储过程的参数集合
        /// </summary>
        /// <param name="parameters"></param>
        private void GetProcedureParameter(DALResult result,params object[] parameters)
        {
            SqlCommand myCommand2 = new SqlCommand();
            myCommand2.Connection = this.myConnection;
            myCommand2.CommandText = "select * from INFORMATION_SCHEMA.PARAMETERS where SPECIFIC_NAME='" +this.ProcedureName+ "' order by ORDINAL_POSITION";
            SqlDataReader reader = null;
            try 
            {
                reader = myCommand2.ExecuteReader();
                int i = 0;
                while(reader.Read())
                {
                    myParameter = new SqlParameter();
                    myParameter.ParameterName = reader["PARAMETER_NAME"].ToString();
                    myParameter.Direction = reader["PARAMETER_MODE"].ToString()=="IN"?ParameterDirection.Input:ParameterDirection.Output;
                    
                    switch(reader["DATA_TYPE"].ToString())
                    {
                        case "bit" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = Convert.ToBoolean(parameters[i]);
                            myParameter.SqlDbType = SqlDbType.Bit;
                            break;
                        
                        case "bigint":
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = Convert.ToInt32(parameters[i]);
                            myParameter.SqlDbType = SqlDbType.BigInt;
                            break;
                       
                        case "int" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = Convert.ToInt32(parameters[i].ToString());
                            myParameter.SqlDbType = SqlDbType.Int;
                            break;

                        case "decimal" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = (decimal)parameters[i];
                            myParameter.SqlDbType = SqlDbType.Decimal;
                            myParameter.Precision = (byte)reader["NUMERIC_PRECISION"];
                            myParameter.Scale = byte.Parse(reader["NUMERIC_SCALE"].ToString());
                            break;

                        case "nvarchar" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = Convert.ToString(parameters[i]);
                            myParameter.Size = Convert.ToInt32(reader["CHARACTER_MAXIMUM_LENGTH"]);
                            myParameter.SqlDbType = SqlDbType.NVarChar;
                            break;

                        case "varchar" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = (string)parameters[i];
                            myParameter.Size = Convert.ToInt32(reader["CHARACTER_MAXIMUM_LENGTH"]);
                            myParameter.SqlDbType = SqlDbType.VarChar;
                            break;

                        case "nchar" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = (string)parameters[i];
                            myParameter.Size = Convert.ToInt32(reader["CHARACTER_MAXIMUM_LENGTH"]);
                            myParameter.SqlDbType = SqlDbType.NChar;
                            break;

                        case "char" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = (string)parameters[i];
                            myParameter.Size = Convert.ToInt32(reader["CHARACTER_MAXIMUM_LENGTH"]);
                            myParameter.SqlDbType = SqlDbType.Char;
                            break;

                        case "ntext" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = (string)parameters[i];
                            myParameter.SqlDbType = SqlDbType.NText;
                            break;
                      
                        case "text" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = (string)parameters[i];
                            myParameter.SqlDbType = SqlDbType.Text;
                            break;
                       
                        case "datetime" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = Convert.ToDateTime(parameters[i]);
                            myParameter.SqlDbType = SqlDbType.DateTime;
                            break; 
                 
                        case "smalldatetime" :
                            if(myParameter.Direction == ParameterDirection.Input)
                                myParameter.Value = Convert.ToDateTime(parameters[i]);
                            myParameter.SqlDbType = SqlDbType.DateTime;
                            break;      
                 
                        case "image" :
                            if(myParameter.Direction == ParameterDirection.Input)
                            {
                                myParameter.Value=(byte[])parameters[i];                            
                            }
                            myParameter.SqlDbType = SqlDbType.Image;
                            break;

                        case "real":
                            if(myParameter.Direction==ParameterDirection.Input)
                                myParameter.Value=Convert.ToSingle(parameters[i]);
                            myParameter.SqlDbType = SqlDbType.Real;
                            break;    
                        case "varbinary":
                            if(myParameter.Direction==ParameterDirection.Input)
                                myParameter.Value=(byte[])parameters[i];
                            myParameter.SqlDbType = SqlDbType.VarBinary;
                            break;

                        default : 
                            break;
                    }
                    i++;
                    myCommand.Parameters.Add(myParameter);
                }
            }
            catch(Exception e)
            {
                result.errorMessage = e.Message;
            }
            finally
            {
                if(reader!=null)
                {
                    reader.Close();
                }
                myCommand2.Dispose();
            }
        }

        /// <summary>
        /// 将输出的值添加到Result的OutputValues
        /// </summary>
        /// <param name="result"></param>
        private void GetOutputValue(DALResult result)
        {
            foreach(SqlParameter parameter in myCommand.Parameters)
            {
                if(parameter.Direction == ParameterDirection.Output)
                {
                    //Hashtab表是一个键值对
                    result.OutputValues.Add(parameter.ParameterName, parameter.Value);
                }
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (! disposing)
                return; 
            if(myConnection != null)
            {
                myConnection.Dispose();
            }
        }
        //=======end======
    }
}

     3.总结

     何时采用外观模式:

     从代码角度来说, 如果你的程序有多个类是和一组其它接口发生关联的话可以考虑在其中加一个外观类型。
     从应用角度来说, 如果子系统的接口是非常细的,调用方也有大量的逻辑来和这些接口发生关系,那么就可以考虑使用Facade把客户端与子系统的直接耦合关系进行化解。你可能会说,子系统改了外观类不是照样改?的确是需要改,但是如果客户端本身的工作已经比较复杂,或者说可能有多个需要调用外观类的地方,这个时候外观类的好处就体现了。

 

     效果及实现要点

     1.Facade模式对客户屏蔽了子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。

     2.Facade模式实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。松耦合关系使得子系统的组件变化不会影响到它的客户。

     3.如果应用需要,它并不限制它们使用子系统类。因此你可以在系统易用性与通用性之间选择。

     4.通过一个高层接口让子系统和客户端不发生直接关联,使客户端不受子系统变化的影响。

     5.Facade不仅仅针对代码级别,在构架上,特别是WEB应用程序的构架上,Facade的应用非常普遍。如常常说的三层架构就是典型的外观模式。