现在的位置: 首页 > 综合 > 正文

设计模式-外观模式(Facade Pattern)

2013年01月22日 ⁄ 综合 ⁄ 共 7980字 ⁄ 字号 评论关闭

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

 

     结构图说明:

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

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

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

     四个子系统类:


    public class SubSystemOne
    
{
        
public void MethodOne()
        
{
            Console.WriteLine(
" 子系统方法一");
        }

    }


    
public class SubSystemTwo
    
{
        
public void MethodTwo()
        
{
            Console.WriteLine(
" 子系统方法二");
        }

    }


    
public class SubSystemThree
    
{
        
public void MethodThree()
        
{
            Console.WriteLine(
" 子系统方法三");
        }

    }


    
public class SubSystemFour
    
{
        
public void MethodFour()
        
{
            Console.WriteLine(
" 子系统方法四");
        }

    }

     外观类:


    public class Facade
    
{
        SubSystemOne one;
        SubSystemTwo two;
        SubSystemThree three;
        SubSystemFour four;

        
public Facade()
        
{
            one 
= new SubSystemOne();
            two 
= new SubSystemTwo();
            three 
= new SubSystemThree();
            four 
= new SubSystemFour();
        }


        
public void MethodA()
        
{
            Console.WriteLine(
"\n方法组A() ---- ");
            one.MethodOne();
            two.MethodTwo();
            four.MethodFour();
        }


        
public void MethodB()
        
{
            Console.WriteLine(
"\n方法组B() ---- ");
            two.MethodTwo();
            three.MethodThree();
        }

    }

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


    public class Program
    
{
        
static void Main(string[] args)
        
{
            Facade facade 
= new Facade();

            facade.MethodA();
            facade.MethodB();

            Console.Read();

        }

    }

     2.实例

     数据库访问外观模式:

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


            SqlConnection myConn = new SqlConnection();
            myConn.ConnectionString 
= "Database=xxx;Server=local;User Id=sa;Password=123456;";
            myConn.Open();
            DataTable dt 
= new DataTable();
            SqlCommand cmd 
= new SqlCommand(strSQL);
            SqlDataAdapter da 
= new SqlDataAdapter(cmd);
            cmd.Connection 
= myConn;
            da.Fill(dt);
            myConn.Close();

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

 


using System;
using System.Data;
using System.Collections;
namespace DAL
{
    
/// <summary>
    
/// DALResult 
    
/// Copyright peida 2008-7-15
    
/// </summary>

    public class DALResult
    
{
        
public bool IsSucceed;            //存储过程是否执行成功
        public string errorMessage;        //访问数据库失败
        public int rowsCount;            //结果集行数.
        public object theFirst;            //第一行第一列
        public Hashtable OutputValues;    //存储过程output值,放在(HashTable)表OutputValues里.        
        public DataTable datatable;        //存储过程返回的结果集,放在(DataTable)表datatable里.
        public DataSet dataSet;            //存储过程返回的结果集,放在DataSet表中

        
public DALResult()
        
{
            IsSucceed 
= false;
            rowsCount 
= 0;
            errorMessage 
= "";
            theFirst 
= null;
            OutputValues 
= new Hashtable();
            datatable
=new DataTable();
            dataSet
=new DataSet();
        }

    }

}

      SQL语句的分装:


using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;

namespace DAL
{
    
/// <summary>
    
/// SQL_Base 调用SQL语句
    
/// Copyright peida 2008-7-15
    
/// </summary>

    public class SQL_Base : IDisposable
    
{
                
private string strconn = "";
        
public SQL_Base() : this("")
        
{
            strconn 
= ConfigurationSettings.AppSettings["DBpath"];
        }

        
//重载
        public SQL_Base(string sql_name)
        
{
            strconn 
= ConfigurationSettings.AppSettings[sql_name];
        }

        
//私有成员变量
        private string sql_name;
        
private SqlConnection myConnection;
        
private SqlCommand myCommand;

        
//公共属性
        public string SQLName
        
{
            
get
            

                
return this.sql_name; 
            }

            
set
            

                
this.sql_name = value; 
            }

        }


        
/// <summary>
        
/// 执行SQL语句,返回数据集:DataTable或DataSet
        
/// </summary>
        
/// <returns>返回DALResult</returns>

        public DALResult ExecuteSqlData()
        
{            
            DALResult result 
= new DALResult();
            myConnection 
= new SqlConnection(strconn);
            myCommand 
= new SqlCommand(this.sql_name, myConnection);
            myCommand.CommandType 
= CommandType.Text;

            SqlDataAdapter myAdapter 
= new SqlDataAdapter(myCommand);    
        
            myConnection.Open();
            
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;
                    
//提交事物
                    trans.Commit();
                }

                
catch(Exception e)
                
{
                    result.errorMessage 
= e.Message;
                }


                
//如果捕捉了异常,但仍会执行包括在 finally 块中的输出语句
                finally
                
{                    
                    myAdapter.Dispose();
                    myCommand.Dispose();
                    myConnection.Close();
                    myConnection.Dispose();                
                }

            }

            
return result;
        }


        
/// <summary>
        
/// 获取第一行第一列数据
        
/// </summary>
        
/// <returns>返回DALResult</returns>

        public DALResult ExecuteSqlScalar()
        
{
            DALResult result 
= new DALResult();
            myConnection 
= new SqlConnection(strconn);
            myCommand 
= new SqlCommand(this.sql_name, myConnection);
            myCommand.CommandType 
= CommandType.Text;
        
            myConnection.Open();
            
using(SqlTransaction trans  = myConnection.BeginTransaction())
            
{
                
try
                
{
                    
if(trans!=null)
                    
{
                        myCommand.Transaction 
= trans;                        
                    }

                    
object scalarresult = myCommand.ExecuteScalar();
                    
if(Object.Equals(scalarresult,null))
                    
{
                        result.errorMessage 
= "没有取到数据";
                    }

                    
else
                    
{
                        result.theFirst 
= scalarresult;
                        
//取到数据
                        result.rowsCount=1;
                    }

                    result.IsSucceed 
= true;
                    
//提交事物
                    trans.Commit();
                }

                
catch(Exception e)
                
{
                    result.errorMessage 
= e.Message;
                }

                
finally
                
{
                    myCommand.Dispose();
                    myConnection.Close();
                    myConnection.Dispose();                
                }

            }

            
return result;
        }


        
/// <summary>

抱歉!评论已关闭.