前言 :
上篇发表之后
朋友们的反应,大多是说太抽象了,好像啥都没讲。
其实观念的东西真的就是抽象,本质真的就是简单两字而已。
呵呵~说的有点多了,
这第二篇主要是补充一个实作的例子,
看会不会比较那么虚无飘渺噜。
架构 :
蓝色框框代表一个独立的DLL
特别标明出来是要传达,
数据存取层的接口定义是跟逻辑层绑在一起的
数据存取层的实作成是是相依于逻辑层内的数据存取层接口
常常工程师在设计软件的时候
会写成 : 逻辑层==>数据存取层
建议的作法是 : 逻辑层(数据存取接口<=)=数据存取层
把相依的方向改变,这是面向对象设计中一个很重要的观念。
范例 :
namespace Clark.Example
{
public class Product
{
public string ProductID = string.Empty;
public string Caption = string.Empty;
public string Description = string.Empty;
}
public interface IProductStore
{
void Add(Product product);
void Update(Product product);
void Delete(Product product);
Product[] GetAll();
}
public class Business
{
private IProductStore _store;
public Business(IProductStore store)
{
_store = store;
}
public int GetProductCount()
{
Product[] products = _store.GetAll();
return products.Length;
}
}
}
namespace Clark.Example.SqlStorage
{
public class SqlProductStore : IProductStore
{
private string _connectionString;
public SqlProductStore(string connectionString)
{
_connectionString = connectionString;
}
public Product[] GetAll()
{
Product product;
List<Product> productList;
SqlConnection conn = new SqlConnection(_connectionString);
SqlCommand cmd = new SqlCommand("SELECT * FROM Products WHERE", conn);
SqlDataReader reader = null;
conn.Open();
reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
productList = new List<Product>();
while (reader.Read())
{
product = new Product();
product.ProductID = reader.GetValue(1).ToString();
product.Caption = reader.GetValue(2).ToString();
product.Description = reader.GetValue(3).ToString();
productList.Add(product);
}
reader.Close();
conn.Dispose();
cmd.Dispose();
return productList.ToArray();
}
public void Add(Product product)
{
//
}
public void Update(Product product)
{
//
}
public void Delete(Product product)
{
//
}
}
}
namespace Clark.ExampleConsole
{
class Program
{
static void Main(string[] args)
{
IProductStore store = CreateStore();
Business business = new Business(store);
Console.WriteLine(business.GetProductCount());
Console.ReadLine();
}
private static IProductStore CreateStore()
{
return new Clark.Example.SqlStorage.SqlProductStore("xxxxx");
}
}
}
说明 :
这支应用程序很简单,主要就是
在屏幕上显示数据存放区内存放的Product的数量
比较需要说明的是一些设计的思路
Clark.Example
Product : 这是需要永续存放的对象。
永续存放这是一个很关键的词,
在观念上我们可以把系统看成下面的图
执行区内是应用程序执行时使用的对象
有时我们会将对象存到可以长久存放的地方(数据库或是其他)
在下次启动时可以取得之前存的对象。
这边要特别注意 : 【存放的是「对象」而不是「数据」】
单纯存放数据的话,很容易陷入数据导向程序设计的思考方向。
IProductStore : 数据存取层定义接口
定义数据存取层,应该实作的接口功能。
定义这个接口要注意的依然是 : 【存放的是「对象」而不是「数据」】
接口功能要定义应该是 : 永续存放的对象,有哪些方法可以通过数据存取层。
Business : 逻辑层对象
系统运作的逻辑对象。
Clark.Example.SqlStorage
SqlProductStore : 实作数据存取层定义接口的对象
这个对象就是实作数据存取层定义接口,存放对象的目的地是SQL数据库。
透过各种实作数据存取层定义接口的对象,
我们可以抽换存放对象目的地,而不用去改到企业逻辑。
Clark.ExampleConsole
Program : 程序代码进入点
这个简单的范例 Program除了是程序代码进入点,
另外他也负责了IProductStore、Business的生成。
范例中的生成模式,并没有将Clark.Example.SqlStorage从系统中松绑。
实际在撰写相关程序的时候
是会透过各种的生成模式,将延伸的Dll松绑的。
对象的生成模式,大家有空可以参考之前文章提到的数据噜。
结语 :
看这篇的朋友
可能还不是很懂我想表达的东西
找时间再多发几篇文章。
透过不同的角度去诠释观念,慢慢的轮廓应该就会浮现了吧 ^^
PS : 呼~用文字表达心中的想法真不是一件简单的事。

