设计模式-创建型模式-工厂模式-批量工厂

开发场景

实际项目中经常需要加工一批对象,这时候如果按部就班的一个一个来生成,效率相对上比较低,最好专门设计独立的批量工厂。很难想象调用“啤酒Factory”的Create()方法的时候,要经过工厂的一些列处理,最后才产生一瓶啤酒,如果有人要搞一件啤酒的时候,就要等24次处理,这就不行了。所以有了批量工厂。

实际项目中的开发过程也与此类似,但需要新增两个步骤。

1.准备生产:之前的实现中,实际加工对象的步骤其实就一个new(),但之前必须编写很多访问配置文件,寻找抽象产品类型需要实例化的产品类型,项目中经常还需要增加很多其他比如记录日志、权限检查之类的操作,这些步骤都被划分到“准备生产”的过程里。

2.配货:这是个可选步骤,在此以实际生产过程做类比,比如我们产5000台手机,但是不一定全是一个颜色的,因此后续实际生产并不是for(int i=0;i<5000;i++)的单纯new(),还需要增加一个配货的过程。

依据单一职责的原则,需要增加三个对象。

1.指定生产的抽象类型(Director):它告诉客户程序在保持IFactory的前提下,生产某类产品的数量,同时由于具体某类产品是由Concrete Factory决定的,因此客户程序实际获得IFactory还需由有Director告诉Assembler并进行替换。例如上面那个手机的情景,就需要Direcotr在用完当前BlackMobileFactory生存3000部黑色手机后,将Clietn的IFactory换成RedMoblieFactory,继续生产2000台红色手机。

2.Director的每一个步骤成为一个决策(Decision):它包括两个信息,例如当决策生产2000台红色手机的时候,它包含数量(2000)和实际加工对象(红色手机实例)两项。

3.为批量的IProduct增加一个集合容器类型,项目中也可以直接使用.net提供的既有集合类型,同时修改Concrete Factory的加工方式,变返回某个单独的IProdcut为返回IProdcut集合。

另外,由于项目中批量的加工任务不一定只有一类产品,因此把Director这个"军师"放到客户程序中的任务,还是交给Assembly完成。

1.装载IProdcut的容器类型

 public class ProductCollection
    {
        private IList<IProduct> _data = new List<IProduct>();

        /// <summary>
        /// 对外的集合操作方法
        /// </summary>
        /// <param name="item"></param>
        public void Insert(IProduct item) { _data.Add(item); }

        public void Insert(IProduct[] items)
        {
            if (items == null || items.Length == 0) return;
            foreach (var item in items) { _data.Add(item); }
        }
        public void Remove(IProduct item) { _data.Remove(item); }
        public void Clear() { _data.Clear(); }

        /// <summary>
        /// 获取所有IProdcut内容的属性
        /// </summary>
        public IProduct[] Data
        {
            get
            {
                if (_data == null || _data.Count == 0) return null;
                var result = new IProduct[_data.Count];
                _data.CopyTo(result, 0);
                return result;
            }
        }
        /// <summary>
        /// 获取当前集合内的元素数量
        /// </summary>
        public int Count => _data.Count;

        /// <summary>
        /// 为了便于操作,重载的运算符
        /// </summary>
        /// <param name="collection"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        public static ProductCollection operator +(ProductCollection collection, IProduct[] items)
        {
            var result = new ProductCollection();
            if (!(collection == null || collection.Count == 0)) result.Insert(collection.Data);
            if (!(items == null || items.Length == 0)) result.Insert(items);
            return result;
        }
        public static ProductCollection operator +(ProductCollection source, ProductCollection target)
        {
            var result = new ProductCollection();
            if (!(source == null || source.Count == 0)) result.Insert(source.Data);
            if (!(target == null || target.Count == 0)) result.Insert(target.Data);
            return result;
        }

    }

2.定义批量工厂和产品类型容器

 public interface IBatchFactory
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="quantity">待加工的产品数量</param>
        /// <returns></returns>
        ProductCollection Create(int quantity);
    }

    /// <summary>
    /// 为了方便提供的抽象基类
    /// </summary>
    /// <typeparam name="T">Concrete Product基类</typeparam>
    public class BatchProductFactoryBase<T> : IBatchFactory where T : IProduct, new()
    {
        public virtual ProductCollection Create(int quantity)
        {
            if (quantity <= 0) throw new ArgumentException();
            var collection = new ProductCollection();
            for (var i = 0; i < quantity; i++) collection.Insert(new T());
            return collection;
        }
    }

    /// <summary>
    /// 两个实体批量生产工厂类型
    /// </summary>
    public class BatchProductAFactory : BatchProductFactoryBase<ProductA> { }

    public class BatchProductBFactory : BatchProductFactoryBase<ProductB> { }

3.

public abstract class DecisionBase
    {
        private readonly IBatchFactory _factory;
        private readonly int _quantity;
        protected DecisionBase(IBatchFactory factory, int quantity)
        {
            _factory = factory; _quantity = quantity;
        }

        public virtual IBatchFactory Factory => _factory;
        public virtual int Quantity => _quantity;
    }

    public abstract class DirectorBase
    {
        private IList<DecisionBase> _decisions = new List<DecisionBase>();

        /// <summary>
        /// 实际项目中,最好将每个Derector需要添加的Decision也定义在配置文件中
        /// 这样增加新的Decison项都在后台完成,而不需要Assembler显示调用该方法补充
        /// </summary>
        /// <param name="decision"></param>
        protected virtual void Inset(DecisionBase decision)
        {
            if (decision == null || decision.Factory == null || decision.Quantity < 0) throw new ArgumentException();
            _decisions.Add(decision);
        }
        /// <summary>
        /// 便于客户程序使用增加的迭代器
        /// </summary>
        public virtual IEnumerable<DecisionBase> Decisions => _decisions;
    }

增加生产指导"顾问"

4.

internal class ProductADecision : DecisionBase
    {
        public ProductADecision() : base(new BatchProductAFactory(), 2) { }
    }

    internal class ProductBDecision : DecisionBase
    {
        public ProductBDecision() : base(new BatchProductBFactory(), 3) { }
    }

    public class ProductDirector : DirectorBase
    {
        public ProductDirector()
        {
            base.Inset(new ProductADecision());
            base.Inset(new ProductBDecision());
        }
    }

由Director指导的客户程序

public class ClientBatch//实现批量工厂的客户代码
    {
        /// <summary>
        /// 实际项目中,可以通过Assembler从外部把Director注入
        /// </summary>
        private DirectorBase _director = new ProductDirector();

        public IProduct[] Produce()
        {
            var collection = new ProductCollection();
            foreach (var decision in _director.Decisions)
            {
                collection += decision.Factory.Create(decision.Quantity);
            }
            return collection.Data;
        }
    }

"客户"程序

[TestMethod]
        public void BatchTest()
        {
            var client = new ClientBatch();
            var products = client.Produce();
            Assert.AreEqual(2 + 3, products.Length);
            for (var i = 0; i < 2; i++) { Assert.AreEqual("A", products[i].Name); }
            for (var i = 2; i < 5; i++) { Assert.AreEqual("B", products[i].Name); }
        }

单元测试

以上。

时间: 2024-07-30 22:16:31

设计模式-创建型模式-工厂模式-批量工厂的相关文章

设计模式(创建型)之原型模式(Prototype Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! 概述 原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据. 原型模式要求对象实现一个可以"克隆"自身的接口,这样就可以通过

设计模式(创建型)之建造者模式(Builder Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! 概述 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端压根不用知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可.它关注如何一步一步创建一个的复杂对象,不同的具体建造者定义了不同的创建过程,且具体建造者相互独立,增加新的建造者非常方便,无须修改已有代码,系统具有较好的扩展性. 问题来了... 你可能会有疑惑,建造者模式和抽象工

【C#设计模式——创建型模式】抽象工厂模式

抽象工厂模式比工厂模式具有更高层次的抽象性.当要返回一系列相关类中的某一个,而每个类都能根据需要返回不同的对象时,可以选择这种模式.直接进入示例. 示例描述:完成花园的规划,多种花园种类,每个里面多种植物 编写一个基类Garden,Garden就是抽象工厂.它定义了具体类中的方法,并返回一系列相关类中的某个类. public class Garden { protected Plant center, shade, border; protected bool showCenter, showS

JDK 源码 阅读 - 2 - 设计模式 - 创建型模式

A.创建型模式 抽象工厂(Abstract Factory) javax.xml.parsers.DocumentBuilderFactory DocumentBuilderFactory通过FactoryFinder实例化具体的Factory. 使用例子: DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilder

设计模式——创建型模式

简单的说我们可以把23种设计模式可以归为三大类,分别是创建型模式.结构型模式和行为型模式. 今天,首先看一下创建型模式.创建型设计模式包括5种:单例模式(Singleton).工厂方法模式(Factory Method).抽象工厂模式(Abstract Factory).建造者模式(Builder).原型模式(Prototype).  1.单例模式(Singleton)        1)简介 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的软件设计模式.在它的核心结

C#设计模式-创建型模式(转)

一.简单工厂模式 简单工厂模式Simple Factory,又称静态工厂方法模式.它是类的创建模式.是由一个工厂对象决定创建出哪一种产品类的实例,是不同的工厂方法模式的一个特殊实现. 优点: u 模式的核心是工厂类,该类中含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅负责"消费"产品. u 简单工厂模式实现了对责任的分割. 缺点: u 当产品类有复杂的多层次等级结构时,工厂类只有它自己.以不变应万变. u 模式中工厂类集中了所

【C#设计模式——创建型模式】工场方法模式

工场方法模式对简单工场模式进行了乔庙的扩展,不是用一个专门的类来决定实例化哪一个子类.相反,超类把这种决定延迟到每个子类.这种模式实际上没有决策点,就是没有直接选择一个子类实例化的决策. 看书上的例子有点复杂,自己写了一个简单例子: 示例目标:对数组进行定向排序 基类FormatList对指定数组进行排序,具体实现交给子类实现 public abstract class FormatList { public int[] result; protected abstract void Forma

设计模式(行为型)之迭代器模式(Iterator Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之观察者模式(Observer Pattern)>http://blog.csdn.net/yanbober/article/details/45484749 概述 在软件构建过程中,集合对象内部结构常常变化各异.但对于这些集合对象,我们希望在不暴露其内部结构

设计模式(行为型)之备忘录模式(Memento Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 阅读前一篇<设计模式(行为型)之中介者模式(Mediator Pattern)>http://blog.csdn.net/yanbober/article/details/45533335 概述 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无

[设计模式-行为型]责任链模式(Chain of Responsibility)

概括 名称 Chain of Responsibility 结构 动机 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. 适用性 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定. 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求. 可处理一个请求的对象集合应被动态指定. 解析 形象比喻: 晚上去上英语课, 为了好开溜坐到了最后一排, 哇, 前面坐了好几个漂亮的MM 哎