顯示具有 Design Pattern 標籤的文章。 顯示所有文章
顯示具有 Design Pattern 標籤的文章。 顯示所有文章

2017年12月27日 星期三

2018 IT邦幫忙鐵人賽 - 以三十個需求的實作來學習設計模式

 鐵人賽    IT邦幫忙      Design Pattern  


前言


第二次參加鐵人賽,主題是:

Learning Design Pattern in 30 real-case practices
以三十個需求的實作來學習設計模式

顧名思義,就是用實例來探討設計模式如何應用,自從2013年學習了設計模式也記錄了一些相關的文章 回頭看一下自己2013年寫的文章,感覺太多細節沒有說到,也用了太簡單的例子來說明; 導致自己也看了很模糊的情況(囧)

所以毅然決然用這次的機會再重新學習並記錄設計模式,目標是能多深入一些(但不要流於理論)及提供更貼近現實需求的範例代碼。

感謝創造設計模式的GoF,它讓我覺得寫程式不再是苦力,而是像藝術家或建築師一樣,可以設計出美麗和風格的代碼!


文章列表


以下連結將連至2018 IT邦幫忙鐵人賽,文章也同步發表在Github上,如有建議或錯誤請您不吝批評指教!

Day 1
Day 2
Day 3
Day 4
Day 5
Day 6
Day 7
Day 8
Day 9
Day 10
Day 11
Day 12
Day 13
Day 14
Day 15
Day 16
Day 17
Day 18
Day 19
Day 20
Day 21
Day 22
Day 23
Day 24
Day 25
Day 26
Day 27
Day 28
Day 29
Day 30





2016年5月18日 星期三

[Domain Driven Design] Use delegate for decoupling

 Driven Design    Design Pattern    Decoupling


Introduction


In this article, I will show how to use delegate to decouple the application and domain layers in DDD (Domain Driven Design).

The situation in this sample is that we want to make the Domain layer independent with other functions on the application layer which have the Data Access methods inside. In other words, the Domain layer should relies on virtual class but not real entities. Thus it can focus on the logic and algorithm in DDD.






Background


Refer to the activity diagram in the following picture. We will insert/update a data in to database. However, there are some business logics inside the insert or update methods. We want to pull the logics and flows out to the Domain, but what left in the Application are only the real insert/update database methods.

We will create the delegates in the logics class of Domain, and then inject the methods of Application into the delegates of logics class.

So the logics class only know the virtual (delegate), but it doesn’t know how and who would implement the virtual (real action).




Environment

l   Visual Studio 2015 Ent.



Implement



Architecture

 


Domain : Interface

// Query delegate
public delegate Profile QueryProfileHandler(string name);
// Insert delegate
public delegate void InsertProfileHandler(Profile profile);
// Update delegate
public delegate void UpdateProfileHandler(Profile profile);

public interface ISaveProfileStrategy
{
        void Merge<T>(T profile) where T : Profile;

        // Event for querying
        event QueryProfileHandler QueryProfile;
        // Event for inserting BlsDeliveryOrders
        event InsertProfileHandler InsertProfile;
        // Event for updating BlsDeliveryOrder
        event UpdateProfileHandler UpdateProfile;
}


Domain : Save Profile Strategy

l   For new profile

public class NewProfileStrategy : ISaveProfileStrategy
{
        public event InsertProfileHandler InsertProfile;
        public event QueryProfileHandler QueryProfile;
        public event UpdateProfileHandler UpdateProfile;

        public void Merge<T>(T profile) where T : Profile
        {
            //HACK : Some logics here ....
            Console.WriteLine("Domain : running some logics in NewProfileStrategy.");

            //Call the delegate
            this.UpdateProfile(profile);
        }
}


l   For exist profile

public class UpdateProfileStrategy : ISaveProfileStrategy
{
        public event InsertProfileHandler InsertProfile;
        public event QueryProfileHandler QueryProfile;
        public event UpdateProfileHandler UpdateProfile;

        public void Merge<T>(T profile) where T : Profile
        {
            //HACK : Some logics here ....
            Console.WriteLine("Domain : running some logics in UpdateProfileStrategy.");

            //Call the delegate
            this.InsertProfile(profile);
        }
}

Ok, now the Domain class relies on the delegate, it is isolated from other layers.


Application : The methods for delegates


public class ProfileDataAccessProvider
{
        public static Profile QueryProfile(string name)
        {
            //HACK : Call the DataAccess method to insert the poco ...
            Console.WriteLine("Application : query the data!");

            return new Profile() { Name = name };
        }

        public static void InsertProfile(Profile profile)
        {
            //HACK : Call the DataAccess method to insert the poco ...
            Console.WriteLine("Application : insert the data!");
        }

        public static void UpdateProfile(Profile profile)
        {
            //HACK : Call the DataAccess method to insert the poco ...
            Console.WriteLine("Application : update the data!");
        }
}


Presentation

Now inject the Service : provider into Domain, now we successfully decouple the Application and Domain layers.

List<Profile> profiles = new List<Profile>() {
                new Profile() {  Name = "JB" },
                new Profile() {  Name = "Lily" }
            };

foreach (var profile in profiles)
{
                ISaveProfileStrategy stg = null;

                //Inject the implement class to interface
                if (profile.Name.Equals("JB"))
                {
                    stg = new UpdateProfileStrategy();
                }
                else
                {
                    stg = new NewProfileStrategy();
                }

                //Inject the methods to delegates
                stg.InsertProfile += ProfileDataAccessProvider.InsertProfile;
                stg.UpdateProfile += ProfileDataAccessProvider.UpdateProfile;
                stg.QueryProfile += ProfileDataAccessProvider.QueryProfile;
               
                //Do the action
                stg.Merge(profile);
               
                //GC
                stg = null;
}


Result

 

Reference