一步一步搭架子(Model繼承與Factory層)


一直覺得,簡單也是一種美,架構如此,做人亦如此;重劍無鋒,真水無香

為了便於大家理解,在此放出源代碼:點擊此處下載

強烈建議配合代碼閱讀本文,畢竟代碼才是程序員最好的交流方式

 

之前的文章分析了系統,並畫出了架構草圖,詳情請見《一步一步搭架子(分析篇)

關於ModelBase層與Model層的實現,因為很簡單,就不再贅述了,直接上代碼即可。關於Model繼承的思路,請見:《我們該如何設計數據庫(三)(續)

ModelBase代碼:

namespace ModelBase
{
    public class Identifier
    {
        [Key]
        public Guid ID { get; set; }
    }

    public class TeacherBase : Identifier
    {
        [StringLength(50)]
        public string UserName { get; set; }

        [StringLength(50)]
        public string Pwd { get; set; }
    }

    public class ContactBase : Identifier
    {
        [Required]
        public Guid TeacherID { get; set; }

        [StringLength(50)]
        public string Phone { get; set; }

        [StringLength(50)]
        public string Email { get; set; }
    }
}

可以看到,數據在這一層是還沒有組合在一起的;然后是Model代碼(假設現在是提供給A學校的):

namespace Model.A
{
    public class Teacher : TeacherBase
    {
        [StringLength(50)]
        public string FirstName { get; set; }

        [StringLength(50)]
        public string LastName { get; set; }

        public Contact Contact { get; set; }
    }

    public class Contact : ContactBase
    {
        public DateTime CreateTime { get; set; }
    }
}

可以看到,Teacher中包含了Contact。我習慣稱這種為“數據耦合在一起”,雖然我不知道這種叫法對不對。歡迎留言指正這種說法

請注意,這里用Model.A的命名空間來區分了Model。如果是B學校的Model,要這樣寫:

namespace Model.B
{
    public class Teacher : TeacherBase
    {
        [StringLength(50)]
        public string Number { get; set; }
    }

    public class Contact : ContactBase
    {
    }
}

可以看到,A學校和B學校Model的命名都是Teacher 和Contact ,用不同的命名空間來加以區分

 

再然后是DBcontext的實現:

using System.Data.Entity;
using Model.A;

namespace DBaccess.A
{
    public class Context : DbContext
    {
        public Context()
        {
            //this.Configuration.AutoDetectChangesEnabled = false;
            //this.Configuration.LazyLoadingEnabled = true;
            //this.Configuration.ProxyCreationEnabled = false;
            //this.Configuration.ValidateOnSaveEnabled = false;
        }

        public DbSet<Teacher> Teacher { get; set; }
        public DbSet<Contact> Contact { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Teacher>()
                .Ignore(o => o.Contact);          //Teacher中的Contact不映射到數據庫中
        }     
    }
}

 

然后就是系統中的難點:Factory的設計

一開始,我覺得這個就是抽象工廠模式所描述的應用場景:同類產品不同產品族的開發

但是在實際開發過程中,卻發現抽象工廠無法滿足需要。抽象工廠要求子類從基類派生,這點我們的Model是由ModelBase派生的,滿足條件;但是我們不同的Model還有自己獨有的get/set方法,而這些獨有的方法是無法通過抽象工廠完成的

簡單的反射也無法滿足要求。反射出來的是一個Object類型,要通過as關鍵字轉換之后才能使用,如:

            Object obj = Assembly.Load("").CreateInstance("");   //假設這里反射出一個Teacher
            Teacher teacher = obj as Teacher;                    //還要as之后才能使用

 

我在這個問題上耗費了一個星期多的時間,直到有一天,靈感突現:可以使用預編譯指令來實現NameSpace的切換

#define A
#if B
using Model.B;
using DBaccess.B;
#endif
#if A
using Model.A;
using DBaccess.A;
#endif

這樣的話,我們切換Model,只需將#define A改為#define B

Factory的具體實現如下:

#region NameSpace
#define A
#if B
using Model.B;
using DBaccess.B;
#endif
#if A
using Model.A;
using DBaccess.A;
#endif
#endregion
using System.Collections.Generic;

namespace Factory
{
    public class ModelFactory
    {
        public static Teacher GetTeacher()
        {
            return new Teacher();
        }       

        public static Contact GetContact()
        {
            return new Contact();
        }   
    }

    public class ModelListFactory
    {
        public static IList<Teacher> GetTeacherList()
        {
            return new List<Teacher>();
        }

        public static IList<Contact> GetContactList()
        {
            return new List<Contact>();
        }
    }

    public class ContextFactory
    {
        public static Context GetContext()
        {
            return new Context();
        }
    }
}

這樣弄出來的Factory,如其名字一樣,用了最簡單的工廠模式來實現

 

就此擱筆

 

PS:變天了,各位園友記得防寒保暖  :)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM