• 规格模式(Specification)


    规格模式(Specification)

    需求如下:需要从数据库的Cargo表中取出商品名称为“钉子”的货物。
    可以这样做:
    public class CargoRepository
    {
     public List SelectByPartName(string partName){}
    }
    当需求发生变化了,它要从数据库的Cargo表中取出商品编码为“0001”的货物。
    可以这样做:
    public class CargoRepository
    {
     public List SelectByPartCode(string partCode){}
    }
    当需求又一次变化了,它要从数据库的Cargo表中取出商品名称为“钉子”并且商品编码为“0001”的货物。
    这时候问题严重了,看下上面的方法都是一些特定的查询,可能还有很多这样的查询。
    他们单个的查询通过组合又形成了新的查询。这就是组合爆炸。
    有两种模式可以解决这样的问题:Specification-[Evans的DDD]和Query Object[Fowler,PEAA]
    这里只讨论Specification


    在对DDD一书中提到:
    (原文如下:业务规则不适于放在任何已个实体或值对象中,而且规则的变化和组合会掩盖那些领域对象的基本含义。)
    有时经常造成组合爆炸。规格是模型的一部分,将它们从实体或值对象中独立出来有助于使模型更加清晰,它表达的是业务的规则。规格是值对象,它用来判断对象是否满足标准的谓词。谓词是指计算结果未true或false的函数,可以用and、or、not操作符连接。

    对规格的接口定义:
    public interface ISpecification
        
    {
            
    bool isSatisfiedBy(object candidate);

            ISpecification and(ISpecification other);
            ISpecification or(ISpecification other);
            ISpecification not();
        }
    我们希望具体的规格只实现isSatisfiedBy方法,所以定义抽象类:
    public abstract class AbstractSpecification : ISpecification
        
    {
            
    ISpecification 成员
    定义操作符谓词:
    internal class AndSpecification : AbstractSpecification
        
    {
            ISpecification one;
            ISpecification other;
            
    public void SetAndSpecification(ISpecification x, ISpecification y)
            
    {
                one 
    = x;
                other 
    = y;
            }

            
    public override bool isSatisfiedBy(object candidate)
            
    {
                
    return one.isSatisfiedBy(candidate) && other.isSatisfiedBy(candidate);
            }

        }
    internal class OrSpecification : AbstractSpecification
        
    {
            ISpecification one;
            ISpecification other;
            
    public void SetOrSpecification(ISpecification x, ISpecification y)
            
    {
                one 
    = x;
                other 
    = y;
            }

            
    public override bool isSatisfiedBy(object candidate)
            
    {
                
    return one.isSatisfiedBy(candidate) || other.isSatisfiedBy(candidate);
            }

        }
    internal class NotSpecification : AbstractSpecification
        
    {
            ISpecification wrapped;
            
    public void SetNotSpecification(ISpecification notSpec)
            
    {
                wrapped 
    = notSpec;
            }

            
    public override bool isSatisfiedBy(object candidate)
            
    {
                
    return !wrapped.isSatisfiedBy(candidate);
            }

        }
    如果使用规格模式,系统中会存在许多小颗粒的规格类。性能会有影响。这里使用享元模式获取规格。
    public class SpecificationFactory
        
    {
            
    private static readonly SpecificationFactory instance = new SpecificationFactory();
            
    private Dictionary<string, ISpecification> m_SpecList;

            
    private SpecificationFactory() { }

            
    public static SpecificationFactory Instance()
            
    {
                
    return instance;
            }


            
    public ISpecification GetSepcification(string assembly,string type)
            
    {
                ISpecification spec;
                
    if (m_SpecList==null{ m_SpecList = new Dictionary<string, ISpecification>(); }
                
    string key = assembly + type;
                
    if (!m_SpecList.ContainsKey(key))
                
    {
                    spec 
    = Assembly.Load(assembly).CreateInstance(type) as ISpecification;
                    
    if (spec!=null{ m_SpecList.Add(key, spec); return spec; }
                    
    throw new Exception(type + "规格不存在,请确保存" + assembly + "中存在" + type + "");
                }

                
    return m_SpecList[key];
            }

        }
    这里简单的测试:

    [TestMethod]
            
    public void TestSpec()
            
    {
                SpecificationFactory sf 
    = SpecificationFactory.Instance();
                Cargo cargo
    =null;
                ISpecification spec 
    = sf.GetSepcification("Bmrxntfj""Bmrxntfj.Specification.NullSpecification");
                Assert.AreEqual(
    true, spec.isSatisfiedBy(cargo));
                spec
    =spec.or(new EqualSpecification());
                Assert.AreEqual(
    true, spec.isSatisfiedBy(cargo));
                cargo 
    = new Cargo();
                cargo.PartCode 
    = 2;
                cargo.PartName 
    = "2";
                Assert.AreEqual(
    false, spec.isSatisfiedBy(cargo));
            }

    然而我们却不常这样做。因为有些ORM框架采用对象的属性来查询。在基础结构层中生成SQL,这样我们就不需要这样麻烦了。
  • 相关阅读:
    【python】装饰器详解推荐
    【React + flask】跨域服务及访问
    【LInux】统计某文件夹下目录的个数
    【NPM】设置代理
    【Mac】jupyter
    【Mac brew】代理安装brew insall
    【医学】超声波成像原理
    【Nginx】配置及使用
    音视频处理ffmpeg使用
    【DL】梯度下降小结
  • 原文地址:https://www.cnblogs.com/bmrxntfj/p/1071359.html
Copyright © 2020-2023  润新知