三层架构学习----PetShop跟彬月论坛对比

彬月论坛

UI层:

(new FavoriteService()).Append(this.TopicID, Visitor.Current.NickName);

业务逻辑层

  public void Append(int topicID, string nickName)
  {
   if (topicID <= 0 || nickName == null || nickName == "")
    return;

   this.DriveFavoriteTask().Append(topicID, nickName);
  }

  /// <summary>
  /// 驱动收藏夹数据库任务
  /// </summary>
  /// <returns></returns>
  private IFavoriteTask DriveFavoriteTask()
  {
   return DBTaskDriverBase.Instance.DriveFavoriteTask();
  }

数据访问层接口定义:

void Append(int topicID, string nickName);

SQLServer数据访问层:

  public void Append(int topicID, string nickName)
  {
   if (topicID <= 0 || nickName == null || nickName == "")
    return;

   MySqlParamCollection parameters = new MySqlParamCollection();

   // 设置主题编号
   parameters.Add("@TopicID", SqlDbType.Int).Value = topicID;
   // 设置用户名称
   parameters.Add("@NickName", SqlDbType.NVarChar, 20).Value = nickName;

   // 执行 SQL 查询
   SQLHelper.ExecuteNoneQuery(SQL_APPEND, CommandType.StoredProcedure, parameters.ToArray());
  }

数据层的抽象工厂:

  /// <summary>
  /// 获取数据库任务驱动实例
  /// </summary>
  /// <returns></returns>
  public static DBTaskDriverBase Instance
  {
   get
   {
    if (g_theInstance != null)
     return g_theInstance;

    lock (typeof(DBTaskDriverBase))
    {
     if (g_theInstance == null)
     {
      Type type = Type.GetType(SystemConfManager.Context.DALConf.ActiveProvider.DBTaskDriver);

      // 建立 DBTaskDriverBase 数据库任务驱动实例
      DBTaskDriverBase instance = Activator.CreateInstance(type) as DBTaskDriverBase;

      g_theInstance = instance;
     }
    }

    // 返回数据库任务驱动实例
    return g_theInstance;
   }
  }

public abstract IFavoriteTask DriveFavoriteTask();

这其中还有掌管接口实例的DBTaskDriver

public override IFavoriteTask DriveFavoriteTask()
  {
   return new FavoriteTask();
  }

我们在看一下PetShop的代码

UI层:

            //get category id
            string categoryKey = Request.QueryString["categoryId"];

            //bind data
            Product product = new Product();
            productsList.DataSource = product.GetProductsByCategory(categoryKey);
            productsList.DataBind();

业务逻辑层

private static readonly IProduct dal = PetShop.DALFactory.DataAccess.CreateProduct();

  public IList<ProductInfo> GetProductsByCategory(string category) {

   // Return new if the string is empty
   if(string.IsNullOrEmpty(category))
    return new List<ProductInfo>();

   // Run a search against the data store
   return dal.GetProductsByCategory(category);
  }

数据访问层接口定义:

IList<ProductInfo> GetProductsByCategory(string category); 

SQLServer数据访问层:

        public IList<ProductInfo> GetProductsByCategory(string category) {

            IList<ProductInfo> productsByCategory = new List<ProductInfo>();

            SqlParameter parm = new SqlParameter(PARM_CATEGORY, SqlDbType.VarChar, 10);
            parm.Value = category;

            //Execute a query to read the products
            using (SqlDataReader rdr = SqlHelper.ExecuteReader(SqlHelper.ConnectionStringLocalTransaction, CommandType.Text, SQL_Select_PRODUCTS_BY_CATEGORY, parm)) {
                while (rdr.Read()) {
                    ProductInfo product = new ProductInfo(rdr.GetString(0), rdr.GetString(1), rdr.GetString(2), rdr.GetString(3), rdr.GetString(4));
                    productsByCategory.Add(product);
                }
            }

            return productsByCategory;
        }

数据层的抽象工厂:

private static readonly string path = ConfigurationManager.AppSettings["WebDAL"];

        public static PetShop.IDAL.IProduct CreateProduct() {
            string className = path + ".Product";
            return (PetShop.IDAL.IProduct)Assembly.Load(path).CreateInstance(className);
        }

我们分析一下,二者实现上的区别:

   PetShop在业务逻辑层中,使用了一个单利,为了不重复建立具体的数据访问层对象,然后,在中间层是调用数据访问层的同名函数,其跟冰月论坛在SQLServer数据访问层上基本相同!只是在数据层的抽象工厂有一些差别!

   在彬月论坛中,业务逻辑层使用return DBTaskDriverBase.Instance.DriveFavoriteTask(),DriveXXXTask() 来建立一个具体的接口实例,而 PetShop 则是使用不同的工厂方法,来建立不同的接口实例!使用PetShop这种方式会在配置文件里写比较多的配置信息。而彬月论坛只写一个配置信息,就可以产生不同的接口实例,不是直接产生某个接口的实例,而是先产生一个被我称之为 DBTaskDriver 的东西,你可以把它视作掌管接口实例的大总管。要想建立接口实例,先得建立这个大总管,然后再由它来建立具体的接口实例。虽然大总管具备建立具体接口的能力,但是他并不能知道到底真的要建立具体哪个实例?所以,只好将他这种能力抽象化,他变成了一个抽象的大总管,而且建立具体接口的能力被推迟到了具体的数据访问层里。这样,我只需要知道:1. 我呼叫大总管, 2. 大总管告诉具体的接口实例,而不是,我呼叫工厂类里的每个具体的工厂!在抽象大总管中,覆盖数据层的抽象工厂里的抽象类!

 

你可能感兴趣的:(三层架构学习----PetShop跟彬月论坛对比)