設計模式 - 12)抽象工廠
阿新 • • 發佈:2020-12-27
class User { int _id; public int Id { get { return _id; } set { _id = value; } } string _name; public string Name { get { return _name; } set { _name = value; } } } interface IUser { void InsertUser(User user); User GetUser(int id); } class SqlserverUser : IUser { public void InsertUser(User user) { Console.WriteLine("Insert into user by Sqlserver"); } public User GetUser(int id) { Console.WriteLine("Get user by Sqlserver"); return null; } } class AccessserverUser : IUser { public void InsertUser(User user) { Console.WriteLine("Insert into user by Accessserver"); } public User GetUser(int id) { Console.WriteLine("Get user by Accessserver"); return null; } } class Department { int _id; public int Id { get { return _id; } set { _id = value; } } string _name; public string Name { get { return _name; } set { _name = value; } } } interface IDepartment { void InsertDepartment(Department department); Department GetDepartment(int id); } class SqlserverDepartment : IDepartment { public void InsertDepartment(Department department) { Console.WriteLine("Insert into Department by Sqlserver"); } public Department GetDepartment(int id) { Console.WriteLine("Get Department by Sqlserver"); return null; } } class AccessserverDepartment : IDepartment { public void InsertDepartment(Department department) { Console.WriteLine("Insert into Department by Accessserver"); } public Department GetDepartment(int id) { Console.WriteLine("Get Department by Accessserver"); return null; } } interface IFactoryDB { IUser CreateUser(); IDepartment CreateDepartment(); } class SqlserverFactory : IFactoryDB { public IUser CreateUser() { return new SqlserverUser(); } public IDepartment CreateDepartment() { return new SqlserverDepartment(); } } class AccessFactory : IFactoryDB { public IUser CreateUser() { return new AccessserverUser(); } public IDepartment CreateDepartment() { return new AccessserverDepartment(); } } User user = new User() { Name = "Boy", Id = 1 }; Department dp = new Department() { Name = "department", Id = 2 }; IFactoryDB dbFactory = new AccessFactory(); IUser iu = dbFactory.CreateUser(); iu.InsertUser(user); iu.GetUser(user.Id); IDepartment idp = dbFactory.CreateDepartment(); idp.InsertDepartment(dp); idp.GetDepartment(dp.Id);
缺點:每增加一個表,就需要新增 3 個類的同時,
修改 IFactory、SqlserverFactory、AccessFactory 類,
這違法了開放-封閉原則。下面使用 DataAccess。
class DataAccess { private static readonly string db = "Sqlserver"; //private static readonly string db = "Access"; //private static readonly string db = "Oracle"; public static IUser CreateUser() { IUser result = null; switch (db) { case "Sqlserver": result = new SqlserverUser(); break; case "Access": result = new AccessserverUser(); break; } return result; } public static IDepartment CreateDepartment() { IDepartment result = null; switch (db) { case "Sqlserver": result = new SqlserverDepartment(); break; case "Access": result = new AccessserverDepartment(); break; } return result; } } //業務程式碼: User user = new User() { Name = "Boy", Id = 1 }; Department dp = new Department() { Name = "department", Id = 2 }; IUser iu = DataAccess.CreateUser(); iu.InsertUser(user); iu.GetUser(user.Id); IDepartment idp = DataAccess.CreateDepartment(); idp.InsertDepartment(dp); idp.GetDepartment(dp.Id);
缺點:如果這時候再加一個 Oracle 資料庫,如果是原來的抽象工廠,只需要加一個 OracleFactory 就可以,現在每個方法的 switch 裡面都得再加一個 case。因此採用反射技術:
namespace WpfApp1.AbstractFactory { class DataAccess { private static readonly string AssemblyName = "WpfApp1"; private static readonly string db = ConfigurationManager.AppSettings["DB"]; public static IUser CreateUser() { string className = AssemblyName + ".AbstractFactory." + db + "User"; return (IUser)Assembly.Load(AssemblyName).CreateInstance(className); } public static IDepartment CreateDepartment() { string className = AssemblyName + ".AbstractFactory." + db + "Department"; return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className); } } // 業務程式碼: User user = new User() { Name = "Boy", Id = 1 }; Department dp = new Department() { Name = "department", Id = 2 }; IUser iu = DataAccess.CreateUser(); iu.InsertUser(user); iu.GetUser(user.Id); IDepartment idp = DataAccess.CreateDepartment(); idp.InsertDepartment(dp); idp.GetDepartment(dp.Id);