• 步步为营 .NET 设计模式学习笔记 二、Abstract Factory(抽象工厂)


         我们以一个线程例子来说明下抽象工厂是如何工作的.平时我们都会收发邮件,那我们就做个邮件引擎线程.
          定义: 抽象工厂模式是一种创建型的模式。上面的比喻说明了抽象工厂就是生产同一个系列产品的东西,因为这一系列的产品是关联的,如果混用就可能出问题,所以就统一的在抽象工厂中进行创建。当要增加一个新的产品系列时,就多写一个工厂子类并添加相应的产品子类就可以了。

    我们来看一个类图。

        图中,我们可以看到,客户需要得到某系列的产品的时候,直接用相应的工厂子类来创建产品就可以了。

    示例用例图

    接来下我们设计个邮件发送的线程实例,先看用例图:

    代码设计

    首先创建一个接口ISaaSProcess.cs:

        /// <summary>
        /// 异步调用接口
        /// </summary>
        public interface ISaaSProcess
        {
            /// <summary>
            /// 启动线程任务
            /// </summary>
            void StartProcess();
            /// <summary>
            /// 停止线程任务
            /// </summary>
            void StopProcess();
            /// <summary>
            /// 显示结果
            /// </summary>
            /// <returns></returns>
            List<string> GetResult();
        }
    

    然后创建一个工厂基类SaaSProcessBase.cs:

    public abstract class SaaSProcessBase : ISaaSProcess
        {
            /// <summary>
            /// 记录Log内容
            /// </summary>
            public List<string> _logContent = new List<string>();
            public SaaSProcessBase()
            {
            }
            #region ISaaSProcess Members
            public void StartProcess()
            {
                try
                {
                    InitialProcess();
                    if (CheckCondition())
                    {
                        DoProcess();
                        EndProcess();
                        ClearProcess();
                    }
                    else
                    {
                        _logContent.Add("条件检测不通过,不能正常启动");
                    }
                }
                catch (Exception ex)
                {
                    _logContent.Add("任务的某个线程执行过程中出现异常" + ex.Message);
    
                }
            }
    
            public void StopProcess()
            {
                SetLastUpdateTime(DateTime.Now);
            }
    
            public List<string> GetResult()
            {
                return _logContent;
            }
            /// <summary>
            /// 记录最后操作时间
            /// </summary>
            /// <param name="time"></param>
            public void SetLastUpdateTime(DateTime time)
            {
                _logContent.Add("线程结束时间是" + time.ToString());
            }
            #endregion
            #region abstract method
            /// <summary>
            /// 检查条件是否符合
            /// </summary>
            /// <returns></returns>
            public abstract bool CheckCondition();
            /// <summary>
            /// 初始化线程
            /// </summary>
            public abstract void InitialProcess();
            /// <summary>
            /// 执行线程任务
            /// </summary>
            public abstract void DoProcess();
            /// <summary>
            /// 结束线程任务
            /// </summary>
            public abstract void EndProcess();
            /// <summary>
            /// 清理线程
            /// </summary>
            public abstract void ClearProcess();
            #endregion
        }
    

    然后创建一个发送邮件的工厂EmailEngine.cs:

    public class EmailEngine : SaaSProcessBase
        {
    
            public override bool CheckCondition()
            {
                return true;
            }
    
            public override void InitialProcess()
            {
                _logContent.Add("所有数据准备完毕");
            }
    
            public override void DoProcess()
            {
                _logContent.Add("邮件发送成功");
            }
    
            public override void EndProcess()
            {
                _logContent.Add("邮件发送结束");
            }
    
            public override void ClearProcess()
            {
                _logContent.Add("邮件数据清理完毕");
            }
            public EmailEngine()
            { }
        }
    

    然后再调用它:

    public partial class Run : Form
        {
            public Run()
            {
                InitializeComponent();
            }
    
            private void btnRun_Click(object sender, EventArgs e)
            {
                ISaaSProcess process = new EmailEngine();
                process.StartProcess();
                process.StopProcess();
                foreach (string result in process.GetResult())
                {
                    rtbResult.AppendText(result + "\n");
                }
            }
        }
    

    运行的结果如下图:

    抽象工厂的优点很明显了,就是在需要用到一系列相关类的地方,它可以使我们不出错的创建出一系列的类实例,而我们在需要添加新的产品系列的时候,完全不需要考虑其他系列的问题,仅需要将相关的抽象类(工厂已经产品)具体化就可以了。缺点也在这个地方,当工厂需要生产多一种产品(不是系列)的时候,改动将波及所有类,比如,浙江打算在每一辆汽车上装一个翅膀,那就需要在工厂中添加一个冲压机(以及各种车型的翅膀模具),还要在焊接科里添加这么一道工序,涂装科以及总装 科里面也一样要 进行相应的调整。

    工厂子类不一定需要实现父类的所有方法,但要使子类有用的话,我们必须使它的所有方法宣布具体化。这里,就引出几种做法:1、工厂父类可以就是一个接口,以确保其 子类一定是具体的;2、我们可以继承抽象的父类,但不完全具体化,这样可以继续细分工厂子类;3、抽象的父类中含有具体的方法,这些方法也可以不加virtual修饰符。最后的这种方法可能是比较灵活一点的。

    抽象工厂主要是用在需要一系列相关联的类协同工作的地方,而且这些系列的数量可能会变多,每一个系列完成的工作都不一样,但是调用接口却是一样的。另外,抽象工厂不适合这样一种情况,即每个系列内部的元素数量不能够确定,也就是说,当初设计的时候,系列中有3个配件,后面又涨成5个,之后又涨到7个,这样的话,要改动的地方将多到让人受不了。

      欢迎拍砖.

  • 相关阅读:
    静水流深,沧笙踏歌
    iOS 进阶 第二十二天(0603)
    iOS 进阶 第二十一天(0531)
    iOS 进阶 第二十天(0520)
    iOS 进阶 第十九天(0423)
    iOS 进阶 第十八天(0423)
    iOS 进阶 第十七天(0420)
    iOS 进阶 第十六天(0419)
    iOS 进阶 第十五天(0417)
    iOS 进阶 第十四天(0416)
  • 原文地址:https://www.cnblogs.com/springyangwc/p/2001649.html
Copyright © 2020-2023  润新知