您的位置:首页 > 其它

在抽象工厂中使用依赖倒置

2014-05-31 09:54 183 查看
本篇实现的效果为:当学校有通知的时候,把通知内容发送到每一个人,如下:





□ 思路
可以把通知内容、通知对象、通知方式、通知行为抽象成类、接口、接口实现,再为一些接口创建对应的抽象工厂及其实现。所有的这些依赖可以通过"依赖倒置容器"来管理。

→关于通知内容,可以封装成一个类
→关于通知对象,可以抽象出基类和实现类
→关于通知对象的Repository,有对应的接口、接口实现,抽象工厂、抽象工厂实现
→关于Email通知方式的Repository,有对应的接口,接口实现,抽象工厂、抽象工厂实现
→关于通知的行为,可以有对应的接口和接口实现
→关于客户端调用,这么些接口和接口实现,以及抽象工厂和抽象工厂实现,我们需要使用"依赖倒置",把所有的依赖注册到依赖倒置容器中,使用的时候,再分别拿出来。

另外,可以为所有的抽象工厂提供一个统一的访问入口,让一个接口实现所有的抽象工厂接口,外部访问的时候,可以通过这个接口拿到所有的抽象工厂。

□ 关于通知内容

可以把通知的对象抽象出一个基类来,学生、老师等继承于这个基类。

using System;

namespace AbstractFactoryDI.Core.Model
{
public abstract class Person
{
public virtual Guid Id { get; set; }
public virtual string PIN { get; set; }
public virtual string Name { get; set; }
public virtual string Surname { get; set; }
public virtual string Email { get; set; }
}

public partial class Student : Person
{
}

public partial class Trainer : Person
{
}
}


□ 关于通知对象的Repository

关于通知对象Person的Repository接口,从中可以获取到通知对象Person的集合。

using System.Collections.Generic;
using AbstractFactoryDI.Core.Model;

namespace AbstractFactoryDI.Core.Repository
{
public interface IPersonRepository
{
IEnumerable<Person> GetAllActivePeople();
}
}


为通知对象Person的Repository接口创建抽象工厂。

using AbstractFactoryDI.Core.Repository;

namespace AbstractFactoryDI.Core.Factories
{
public interface IRepositoryFactory
{
IPersonRepository CreatePersonRepository();
}
}


针对IPersonRepository的实现是:

using System;
using System.Collections.Generic;
using System.Linq;
using AbstractFactoryDI.Core.Model;
using AbstractFactoryDI.Core.Repository;

namespace AbstractFactoryDI.Infrastructure.Repository
{
public class PersonRepository : IPersonRepository
{
private static ICollection<Person>  _people = new List<Person>()
{
new Student(){Id = Guid.NewGuid(),Name = "jack", Surname = "cute jack",Email = "jack@sina.com", PIN = "001"},
new Student(){Id = Guid.NewGuid(),Name = "sunny", Surname = "cute sunny",Email = "sunny@sina.com", PIN = "002"},
};
public System.Collections.Generic.IEnumerable<Core.Model.Person> GetAllActivePeople()
{
return _people.AsEnumerable();
}
}
}


□ 关于通知方式中的Email通知

把通过Email通知的方式也抽象成一个接口。

using System;

namespace AbstractFactoryDI.Core.Notificators
{
public interface IEmailNotificator : IDisposable
{
void SendNotification(string toAddress, string message);
}
}


与IEmailNotificator对应的抽象工厂为:

using AbstractFactoryDI.Core.Notificators;

namespace AbstractFactoryDI.Core.Factories
{
public interface IEmailNotificatorFactory
{
IEmailNotificator CreateEmailNotificator();
}
}


IEmailNotificator接口实现是:

using System;
using AbstractFactoryDI.Core.Notificators;

namespace AbstractFactoryDI.Infrastructure.Notificators
{
public class EmailNotificator : IEmailNotificator
{

public void SendNotification(string toAddress, string message)
{
//System.Net.Mail.SmtpClient发邮件
Console.WriteLine(message);
Console.WriteLine();
Console.WriteLine();
}

public void Dispose()
{
//dispose System.Net.Mail.SmtpClient
}
}
}


□ 关于抽象工厂的统一入口

现在已经有了有关通知对象的抽象工厂IRepositoryFactory和有关邮件通知方式的抽象工厂IEmailNotificatorFactory,我们还希望为所有的这些抽象工厂创建一个统一的访问入口,于是创建实现所有抽象工厂接口的接口:

namespace AbstractFactoryDI.Core.Factories
{
public interface IServiceFactory : IRepositoryFactory, IEmailNotificatorFactory
{

}
}


IServiceFactory对应的实现是:

using AbstractFactoryDI.Core.Factories;
using AbstractFactoryDI.Infrastructure.Notificators;
using AbstractFactoryDI.Infrastructure.Repository;

namespace AbstractFactoryDI.Factories.Concrete
{
public class ServiceFactory : IServiceFactory
{

public virtual Core.Repository.IPersonRepository CreatePersonRepository()
{
return new PersonRepository();
}

public virtual Core.Notificators.IEmailNotificator CreateEmailNotificator()
{
return new EmailNotificator();
}
}
}


□ 关于通知内容

通知内容包含放假开始时间、结束时间、内容等,把之封装成一个类。

using System;

namespace AbstractFactoryDI.Core.Services
{
public class ClosureInfo
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string Reason { get; set; }
}
}


□ 关于通知行为

发送通知需要以上的ClosureInfo类型参数,考虑到发送通知的方式可能有多种,比如短信、邮件等,可以为发送通知抽象出一个接口。

namespace AbstractFactoryDI.Core.Services
{
public interface INotificationService
{
void NotifySchoolClosure(ClosureInfo info);
}
}


关于INotificationService的实现。我们可以从抽象工厂统一入口拿到IPersonRepository,从而获取到所有的通知对象。还可以从抽象工厂统一入口拿到IEmailNotificator,来发送通知信息。

using System.Collections.Generic;
using System.Text;
using AbstractFactoryDI.Core.Factories;
using AbstractFactoryDI.Core.Model;

namespace AbstractFactoryDI.Core.Services
{
public class NotificationService : INotificationService
{
private readonly IServiceFactory _factory;

public NotificationService(IServiceFactory factory)
{
_factory = factory;
}
public void NotifySchoolClosure(ClosureInfo info)
{
var personRepository = _factory.CreatePersonRepository();
var people = personRepository.GetAllActivePeople();
NotifySchoolClosure(info, people);
}

private void NotifySchoolClosure(ClosureInfo info, IEnumerable<Person> people)
{
using (var notificator = _factory.CreateEmailNotificator())
{
foreach (var person in people)
{
notificator.SendNotification(person.Email, FormatMessage(person, info));
}
}
}

private string FormatMessage(Person person, ClosureInfo info)
{
var str = new StringBuilder();
str.Append(string.Format("您好 {0}\n", person.Name));
str.Append(info.Reason);
str.Append(string.Format(" 学校将在{0}和{1}期间放假\n", info.StartDate, info.EndDate));
str.Append("请注意安全~~");
return str.ToString();
}
}
}


□ 客户端

前面已经有了抽象工厂以及抽象工厂的实现,抽象工厂入口以及抽象工厂入口的实现,接口和接口实现......所有的这些,都可以让依赖倒置来解决,这里使用Microsoft.Practices.Unity。

using AbstractFactoryDI.Core.Factories;
using AbstractFactoryDI.Core.Services;
using AbstractFactoryDI.Factories.Concrete;
using Microsoft.Practices.Unity;

namespace AbstractFactoryDI.Client
{
public class RootContainer
{
private static readonly UnityContainer _container;

static RootContainer()
{
_container = new UnityContainer();
RegisterAll();
}

internal static void RegisterAll()
{
_container.RegisterType<IEmailNotificatorFactory, ServiceFactory>();
_container.RegisterType<IRepositoryFactory, ServiceFactory>();
_container.RegisterType<IServiceFactory, ServiceFactory>();
_container.RegisterType<INotificationService, NotificationService>();
}

internal static Iofs Resolve<Iofs>()
{
return _container.Resolve<Iofs>();
}
}
}


客户端调用的时候,首先在构造函数中注册所有的依赖,然后在使用的时候,在从依赖倒置容器中解析出具体的接口实现。

using System;
using AbstractFactoryDI.Core.Services;

namespace AbstractFactoryDI.Client
{
class Program
{
public Program()
{
RootContainer.RegisterAll();
}

static void Main(string[] args)
{
NotifyChristmasVacation();
Console.ReadKey();
}

static void NotifyChristmasVacation()
{
INotificationService notificaitonService = RootContainer.Resolve<INotificationService>();
var closureInfo = new ClosureInfo()
{
StartDate = new DateTime(DateTime.Now.Year, 12, 24),
EndDate = new DateTime(DateTime.Now.Year, 12, 26),
Reason = "圣诞节放假~~"
};
notificaitonService.NotifySchoolClosure(closureInfo);
}
}
}


参考资料:

Dependency Injection of an Abstract Factory
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐