看上去很美:外观模式
在软件开发系统中,客户程序经常会与复杂系统的内部子系统之间产生耦合,而导致客户程序随着子系统的变化而变化。举例来说,比如利用传统的三层结构,我们开发了一个客户订单管理系统,数据库表包括主要客户表,订单表,产品表。在该应用程序中,有部分操作只是简单的从数据库根据条件提取数据,不需要经过任何处理,而直接将数据显示到网页上,比如客户登陆显示等级和积分。而另外一些操作,比如客户预定定单中计算购买产品的总价并根据顾客的级别计算回扣,积分和等级之间的相互转换(等级按照积分的变化而变化)等等,这部分往往有许多不同的功能的类,操作起来也比较复杂。如果采用传统的三层结构,这些逻辑一般是会放在中间层,那么对内部的这些大量种类繁多,使用方法也各异的不同的类的调用任务,就完全落到了表示层。这样势必会增加表示层的代码量,将表示层的任务复杂化,和表示层只负责接受用户的输入并返回结果的任务不太相称,并增加了层与层之间的耦合程度。
那么如何简化客户程序与子系统之间的交互接口?如何将复杂系统的内部子系统与客户程序之间的依赖解耦?
于是就引入了一个Facade层,让这个Facade来负责管理系统内部类的调用,并为表示层提供了一个单一而简单的接口。好了,Code is cheap.看代码了先。
类图:
代码部分:
Code
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
namespace FacadePattern
{
/* 简单三层架构的Façade模式运用 表现层,业务逻辑层和数据访问层 */
/* 1.数据访问层,底层数据访问方法(可以参考网上的sqlhelper类,这里仅仅举个示例) */
namespace DataAccessLayer
{
public static class SqlHelper{
//这里的数据库可以自己配置
private static string sqlConStr ="";// System.Configuration.ConfigurationSettings.AppSettings["SqlConnectionString"];
private static SqlConnection sqlCon;
private static DataTable dt;
private static SqlCommand cmd;
private static DataSet ds;
private static SqlDataAdapter da;
//构造函数,创建对象实例
static SqlHelper()
{
sqlCon = new SqlConnection(sqlConStr);
cmd = sqlCon.CreateCommand();
ds = new DataSet();
da = new SqlDataAdapter();
}
/// <summary>
/// 断开连接
/// </summary>
public static void DisConnect()
{
sqlCon = null;
Console.WriteLine("Close database connection success.");
}
public static DataTable GetDataTable(string sqlStr)
{
try
{
cmd.CommandText = sqlStr;
da.SelectCommand = cmd;
da.Fill(ds);
dt = ds.Tables[0];
}
catch (SqlException sqlExp)
{
throw sqlExp;
}
finally
{
DisConnect();
}
return dt;
}
/// <summary>
/// 直接执行sql语句,如插入,删除,更新等等
/// </summary>
/// <param name="sqlStr"></param>
public static void CommitSql(string sqlStr)
{
try
{
cmd.CommandText = sqlStr;
cmd.ExecuteNonQuery();
}
catch (SqlException sqlExp)
{
throw sqlExp;
}
finally
{
DisConnect();
}
}
}
}
/* 2. Customer,Order 实体类 可以属于表现层或者业务逻辑层,这个没必要绝对区分,jeff wong通常放在业务逻辑层 */
namespace BusinessLayer
{
using DataAccessLayer;
public class Customer
{
/// <summary>
/// 客户账户,唯一
/// </summary>
private string signName;
public string SignName
{
get { return signName; }
set { signName = value; }
}
private string password;
public string Password
{
get { return password; }
set { password = value; }
}
private int point;
/// <summary>
/// 客户积分,这个在登陆后直接显示
/// </summary>
public int Point
{
get { return point; }
set { point = value; }
}
private int level;
/// <summary>
/// 客户等级,这个在登陆后直接显示
/// </summary>
public int Level
{
get { return level; }
set { level = value; }
}
public Customer(string signName, string pwd)
{
this.signName = signName;
this.password = pwd;
}
public bool IsCurrentCustomerExists(Customer customer)
{
bool flag = false;
DataTable dt = DataAccessLayer.SqlHelper.GetDataTable(string.Format("SELECT COUNT(*) AS CustomerNum FROM Customer WHERE SignName='{0}' AND Password='{1}'", customer.SignName, customer.Password));
if ((int)(dt.Rows[0][0]) > 0)
flag = true;
return flag;
}
}
/// <summary>
/// 订单实体类 在客户预订单的时候,需要计算积分和客户等级
/// </summary>
public class Order
{
private long orderId;
public long OrderId
{
get { return orderId; }
set { orderId = value; }
}
private string customerName;
/// <summary>
/// 这个对于客户实体类的signname
/// </summary>
public string CustomerName
{
get { return customerName; }
set { customerName = value; }
}
private double price;
public double Price
{
get { return price; }
set { price = value; }
}
private string productId;
public string ProductId
{
get { return productId; }
set { productId = value; }
}
public void AddOrder(Order tmpOrder)
{
string sqlStr = string.Format("INSERT INTO Order(CustomerName,Price,ProductId) VALUES ('{0}','{1}',{2})", tmpOrder.CustomerName, tmpOrder.Price, tmpOrder.ProductId);
}
}
}
namespace FacadeLayer
{
using BusinessLayer; //引用业务逻辑层
using DataAccessLayer; //严格来讲表现层不能引用数据访问层
public class BizFacade
{
private Customer customer;
private Order order;
public void UserLogin(Customer customer)
{
if (customer.IsCurrentCustomerExists(customer))
Console.WriteLine("Login succeed!");
else
Console.WriteLine("Login failed!");
}
public void AddOrder(Customer customer, Order tmpOrder)
{
/* 这里需要对添加订单的一些条件进行判断和计算,比如是否是合法客户,计算客户当前积分和等级,产品库存的加减计算等等,
* 由于逻辑较为复杂,这里省略其他过程,只验证是否是合法客户,然后添加客户订单 */
if (customer.IsCurrentCustomerExists(customer))
{
// 省略其他复杂逻辑
tmpOrder.AddOrder(tmpOrder);
Console.WriteLine("Add order succeed!");
}
else
Console.WriteLine("Add order failed!");
}
}
}
namespace UILayer
{
using BusinessLayer;
using FacadeLayer; //引用业务外观层
public class Program
{
public static void Main()
{
Customer tmpCustomer = new Customer("Jeff Wong", "cnblogs");
BizFacade facade = new BizFacade();
facade.UserLogin(tmpCustomer);
Order tmpOrder=new Order();
tmpOrder.CustomerName="Jeff Wong";
tmpOrder.Price=1000;
tmpOrder.ProductId="123456";
facade.AddOrder(tmpCustomer, tmpOrder);
Console.ReadLine();
}
}
}
}
using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;
namespace FacadePattern
{
/* 简单三层架构的Façade模式运用 表现层,业务逻辑层和数据访问层 */
/* 1.数据访问层,底层数据访问方法(可以参考网上的sqlhelper类,这里仅仅举个示例) */
namespace DataAccessLayer
{
public static class SqlHelper{
//这里的数据库可以自己配置
private static string sqlConStr ="";// System.Configuration.ConfigurationSettings.AppSettings["SqlConnectionString"];
private static SqlConnection sqlCon;
private static DataTable dt;
private static SqlCommand cmd;
private static DataSet ds;
private static SqlDataAdapter da;
//构造函数,创建对象实例
static SqlHelper()
{
sqlCon = new SqlConnection(sqlConStr);
cmd = sqlCon.CreateCommand();
ds = new DataSet();
da = new SqlDataAdapter();
}
/// <summary>
/// 断开连接
/// </summary>
public static void DisConnect()
{
sqlCon = null;
Console.WriteLine("Close database connection success.");
}
public static DataTable GetDataTable(string sqlStr)
{
try
{
cmd.CommandText = sqlStr;
da.SelectCommand = cmd;
da.Fill(ds);
dt = ds.Tables[0];
}
catch (SqlException sqlExp)
{
throw sqlExp;
}
finally
{
DisConnect();
}
return dt;
}
/// <summary>
/// 直接执行sql语句,如插入,删除,更新等等
/// </summary>
/// <param name="sqlStr"></param>
public static void CommitSql(string sqlStr)
{
try
{
cmd.CommandText = sqlStr;
cmd.ExecuteNonQuery();
}
catch (SqlException sqlExp)
{
throw sqlExp;
}
finally
{
DisConnect();
}
}
}
}
/* 2. Customer,Order 实体类 可以属于表现层或者业务逻辑层,这个没必要绝对区分,jeff wong通常放在业务逻辑层 */
namespace BusinessLayer
{
using DataAccessLayer;
public class Customer
{
/// <summary>
/// 客户账户,唯一
/// </summary>
private string signName;
public string SignName
{
get { return signName; }
set { signName = value; }
}
private string password;
public string Password
{
get { return password; }
set { password = value; }
}
private int point;
/// <summary>
/// 客户积分,这个在登陆后直接显示
/// </summary>
public int Point
{
get { return point; }
set { point = value; }
}
private int level;
/// <summary>
/// 客户等级,这个在登陆后直接显示
/// </summary>
public int Level
{
get { return level; }
set { level = value; }
}
public Customer(string signName, string pwd)
{
this.signName = signName;
this.password = pwd;
}
public bool IsCurrentCustomerExists(Customer customer)
{
bool flag = false;
DataTable dt = DataAccessLayer.SqlHelper.GetDataTable(string.Format("SELECT COUNT(*) AS CustomerNum FROM Customer WHERE SignName='{0}' AND Password='{1}'", customer.SignName, customer.Password));
if ((int)(dt.Rows[0][0]) > 0)
flag = true;
return flag;
}
}
/// <summary>
/// 订单实体类 在客户预订单的时候,需要计算积分和客户等级
/// </summary>
public class Order
{
private long orderId;
public long OrderId
{
get { return orderId; }
set { orderId = value; }
}
private string customerName;
/// <summary>
/// 这个对于客户实体类的signname
/// </summary>
public string CustomerName
{
get { return customerName; }
set { customerName = value; }
}
private double price;
public double Price
{
get { return price; }
set { price = value; }
}
private string productId;
public string ProductId
{
get { return productId; }
set { productId = value; }
}
public void AddOrder(Order tmpOrder)
{
string sqlStr = string.Format("INSERT INTO Order(CustomerName,Price,ProductId) VALUES ('{0}','{1}',{2})", tmpOrder.CustomerName, tmpOrder.Price, tmpOrder.ProductId);
}
}
}
namespace FacadeLayer
{
using BusinessLayer; //引用业务逻辑层
using DataAccessLayer; //严格来讲表现层不能引用数据访问层
public class BizFacade
{
private Customer customer;
private Order order;
public void UserLogin(Customer customer)
{
if (customer.IsCurrentCustomerExists(customer))
Console.WriteLine("Login succeed!");
else
Console.WriteLine("Login failed!");
}
public void AddOrder(Customer customer, Order tmpOrder)
{
/* 这里需要对添加订单的一些条件进行判断和计算,比如是否是合法客户,计算客户当前积分和等级,产品库存的加减计算等等,
* 由于逻辑较为复杂,这里省略其他过程,只验证是否是合法客户,然后添加客户订单 */
if (customer.IsCurrentCustomerExists(customer))
{
// 省略其他复杂逻辑
tmpOrder.AddOrder(tmpOrder);
Console.WriteLine("Add order succeed!");
}
else
Console.WriteLine("Add order failed!");
}
}
}
namespace UILayer
{
using BusinessLayer;
using FacadeLayer; //引用业务外观层
public class Program
{
public static void Main()
{
Customer tmpCustomer = new Customer("Jeff Wong", "cnblogs");
BizFacade facade = new BizFacade();
facade.UserLogin(tmpCustomer);
Order tmpOrder=new Order();
tmpOrder.CustomerName="Jeff Wong";
tmpOrder.Price=1000;
tmpOrder.ProductId="123456";
facade.AddOrder(tmpCustomer, tmpOrder);
Console.ReadLine();
}
}
}
}
作者:Jeff Wong
出处:http://jeffwongishandsome.cnblogs.com/
本文版权归作者和博客园共有,欢迎围观转载。转载时请您务必在文章明显位置给出原文链接,谢谢您的合作。