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
沒有留言:
張貼留言