using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SpecificationPattern.ProgramT
{
    public class Mobile
    {
        public BrandName BrandName { get; set; }
        public Type Type { get; set; }
        public int Cost;
        public string GetDescription()
        {
            return "The mobile is of brand : " + this.BrandName + " and of type : " + this.Type;
        }

public Mobile(BrandName brandName, Type type, int cost = 0)
        {
            this.BrandName = brandName;
            this.Type = type;
            this.Cost = cost;
        }
    }

public enum BrandName
    {
        Samsung,
        Apple,
        Htc
    }

public enum Type
    {
        Basic,
        Smart
    }

public interface ISpecification<T>
    {
        bool IsSatisfiedBy(T o);
        ISpecification<T> And(ISpecification<T> specification);
        ISpecification<T> Or(ISpecification<T> specification);
        ISpecification<T> Not(ISpecification<T> specification);
    }

public abstract class CompositeSpecification<T> : ISpecification<T>
    {
        public abstract bool IsSatisfiedBy(T o);

public ISpecification<T> And(ISpecification<T> specification)
        {
            return new AndSpecification<T>(this, specification);
        }
        public ISpecification<T> Or(ISpecification<T> specification)
        {
            return new OrSpecification<T>(this, specification);
        }
        public ISpecification<T> Not(ISpecification<T> specification)
        {
            return new NotSpecification<T>(specification);
        }
    }

public class AndSpecification<T> : CompositeSpecification<T>
    {
        ISpecification<T> leftSpecification;
        ISpecification<T> rightSpecification;

public AndSpecification(ISpecification<T> left, ISpecification<T> right)
        {
            this.leftSpecification = left;
            this.rightSpecification = right;
        }

public override bool IsSatisfiedBy(T o)
        {
            return this.leftSpecification.IsSatisfiedBy(o)
                && this.rightSpecification.IsSatisfiedBy(o);
        }
    }

public class OrSpecification<T> : CompositeSpecification<T>
    {
        ISpecification<T> leftSpecification;
        ISpecification<T> rightSpecification;

public OrSpecification(ISpecification<T> left, ISpecification<T> right)
        {
            this.leftSpecification = left;
            this.rightSpecification = right;
        }

public override bool IsSatisfiedBy(T o)
        {
            return this.leftSpecification.IsSatisfiedBy(o)
                || this.rightSpecification.IsSatisfiedBy(o);
        }
    }

public class NotSpecification<T> : CompositeSpecification<T>
    {
        ISpecification<T> specification;

public NotSpecification(ISpecification<T> spec)
        {
            this.specification = spec;
        }

public override bool IsSatisfiedBy(T o)
        {
            return !this.specification.IsSatisfiedBy(o);
        }
    }

public class ExpressionSpecification<T> : CompositeSpecification<T>
    {
        private Func<T, bool> expression;
        public ExpressionSpecification(Func<T, bool> expression)
        {
            if (expression == null)
                throw new ArgumentNullException();
            else
                this.expression = expression;
        }

public override bool IsSatisfiedBy(T o)
        {
            return this.expression(o);
        }
    }

public class PremiumSpecification<T> : CompositeSpecification<T>
    {
        private int cost;
        public PremiumSpecification(int cost)
        {
            this.cost = cost;
        }

public override bool IsSatisfiedBy(T o)
        {
            return (o as Mobile).Cost >= this.cost;
        }
    }

class ProgramT
    {
        static void Main(string[] args)
        {
            List<Mobile> mobiles = new List<Mobile> {
                new Mobile(BrandName.Samsung, Type.Smart, 700),
                new Mobile(BrandName.Apple, Type.Smart, 800),
                new Mobile(BrandName.Htc, Type.Basic),
                new Mobile(BrandName.Samsung, Type.Basic) };

ISpecification<Mobile> samsungExpSpec =
               new ExpressionSpecification<Mobile>(o => o.BrandName == BrandName.Samsung);
            ISpecification<Mobile> htcExpSpec =
               new ExpressionSpecification<Mobile>(o => o.BrandName == BrandName.Htc);
            ISpecification<Mobile> SamsungAndHtcSpec = samsungExpSpec.And(htcExpSpec);

ISpecification<Mobile> SamsungHtcExpSpec =
               samsungExpSpec.Or(htcExpSpec);
            ISpecification<Mobile> NoSamsungExpSpec = new ExpressionSpecification<Mobile>(o => o.BrandName != BrandName.Samsung);

ISpecification<Mobile> brandExpSpec = new ExpressionSpecification<Mobile>(o => o.Type == Type.Smart);
            ISpecification<Mobile> premiumSpecification = new PremiumSpecification<Mobile>(600);
            ISpecification<Mobile> complexSpec = (samsungExpSpec.Or(htcExpSpec)).And(brandExpSpec);
            ISpecification<Mobile> linqNonLinqExpSpec = NoSamsungExpSpec.And(premiumSpecification);

//Some fun
            Console.WriteLine("\n***Samsung mobiles*****\n");
            var result = mobiles.FindAll(o => samsungExpSpec.IsSatisfiedBy(o));
            result.ForEach(o => Console.WriteLine(o.GetDescription()));

Console.WriteLine("\n*****Htc mobiles********\n");
            result = mobiles.FindAll(o => htcExpSpec.IsSatisfiedBy(o));
            result.ForEach(o => Console.WriteLine(o.GetDescription()));

Console.WriteLine("\n****Htc and samsung mobiles*******\n");
            result = mobiles.FindAll(o => SamsungHtcExpSpec.IsSatisfiedBy(o));
            result.ForEach(o => Console.WriteLine(o.GetDescription()));

Console.WriteLine("\n****Not samsung*******\n");
            result = mobiles.FindAll(o => NoSamsungExpSpec.IsSatisfiedBy(o));
            result.ForEach(o => Console.WriteLine(o.GetDescription()));

Console.WriteLine("\n****Htc and samsung mobiles (only smart)*******\n");
            result = mobiles.FindAll(o => complexSpec.IsSatisfiedBy(o));
            result.ForEach(o => Console.WriteLine(o.GetDescription()));

//More fun
            Console.WriteLine("\n****All premium mobile phones*******\n");

result = mobiles.FindAll(o => premiumSpecification.IsSatisfiedBy(o));
            result.ForEach(o => Console.WriteLine(o.GetDescription()));

Console.WriteLine("\n****All premium mobile phones except samsung*******\n");
            result = mobiles.FindAll(o => linqNonLinqExpSpec.IsSatisfiedBy(o));
            result.ForEach(o => Console.WriteLine(o.GetDescription()));
            Console.ReadLine();
        }

}

}

Specification模式的一个不错的示例代码的更多相关文章

  1. 相邻div实现一个跟着另一个自适应高度示例代码

    方法一: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> < ...

  2. 用vuex写了一个购物车H5页面的示例代码

    用vuex写了一个购物车H5页面的示例代码:https://www.jb51.net/article/152008.htm 通过购物车的一个案列,把vuex学习了一篇. vuex概念浅谈 Vuex 是 ...

  3. 非常不错的一个JS分页效果代码

    这里分享一个不错的js分页代码. 代码中cpage是页面计数,应为全局变量,可以随处调用它: totalpage是总页数. 与asp分页代码很类似,也是先取得记录总数,然后实现分页,基本的分页思路与原 ...

  4. 3.NetDh框架之缓存操作类和二次开发模式简单设计(附源码和示例代码)

    前言 NetDh框架适用于C/S.B/S的服务端框架,可用于项目开发和学习.目前包含以下四个模块 1.数据库操作层封装Dapper,支持多种数据库类型.多库实例,简单强大: 此部分具体说明可参考博客: ...

  5. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

  6. 一个非常标准的Java连接Oracle数据库的示例代码

    最基本的Oracle数据库连接代码(只针对Oracle11g): 1.右键项目->构建路径->配置构建路径,选择第三项“库”,然后点击“添加外部Jar”,选择“D:\Oracle\app\ ...

  7. java 添加一个线程、创建响应的用户界面 。 演示示例代码

    javajava 添加一个线程.创建响应的用户界面 . 演示示例代码 来自thinking in java 4 21章  部分的代码  夹21.2.11 thinking in java 4免费下载: ...

  8. 一个非常标准的连接Mysql数据库的示例代码

    一.About Mysql 1.Mysql 优点 体积小.速度快.开放源码.免费 一般中小型网站的开发都选择 MySQL ,最流行的关系型数据库 LAMP / LNMP Linux作为操作系统 Apa ...

  9. 一个 11 行 Python 代码实现的神经网络

    一个 11 行 Python 代码实现的神经网络 2015/12/02 · 实践项目 · 15 评论· 神经网络 分享到:18 本文由 伯乐在线 - 耶鲁怕冷 翻译,Namco 校稿.未经许可,禁止转 ...

随机推荐

  1. 【高斯消元解xor方程组】BZOJ2466-[中山市选2009]树

    [题目大意] 给出一棵树,初始状态均为0,每反转一个节点的状态,相邻的节点(父亲或儿子)也会反转,问要使状态均为1,至少操作几次? [思路] 一场大暴雨即将来临,白昼恍如黑夜!happy! 和POJ1 ...

  2. Problem F: 尖兵

    #include<stdio.h> struct man{ ]; int grade; }; int main(void) { int t; int i,j,n; ],max; scanf ...

  3. [转]MySQL更改用户密码

    grant all privilegeson *.* to root@'localhost'identified by 'root'with grant option; grant all privi ...

  4. 椭圆曲线加密算法(ECC)原理和C++实现源码(摘录)

    /* 1.用户A选定一条适合加密的椭圆曲线Ep(a,b)(如:y2=x3+ax+b),并取椭圆曲线上一点,作为基点G. 2.用户A选择一个私有密钥k,并生成公开密钥K=kG. 3.用户A将Ep(a,b ...

  5. [典型漏洞分享]结合YS业务分析使用oauth协议的风险

    结合YS业务分析oauth协议风险 问题描述: YS 使用QQ互联的openAPI实现QQ登录YS的功能,使用该功能需要在腾讯注册登录时的回调地址,根据oauth协议,用户的code或者access_ ...

  6. 探索 vuex 2.0 以及使用 vuejs 2.0 + vuex 2.0 构建记事本应用23

    前言 首先说明这并不是一个教程贴,而记事本应用是网上早有的案例,对于学习 vuex 非常有帮助.我的目的是探索 vuex 2.0 ,然后使用 vuejs 2.0 + vuex 2.0 重写这个应用,其 ...

  7. 基本C库函数

    当编写驱动程序时,一般情况下不能使用C标准库的函数.Linux内核也提供了与标准库函数功能相同的一些函数,但二者还是稍有差别. 类别 函数名 功能 函数形成 参数 描述 字符串转换 simple_st ...

  8. 转载:做ArcEngine的二次开发出现“没有注册类别 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG)”

    转自:http://blog.sina.com.cn/s/blog_638e61a40100ynnc.html 出现这个问题主要是因为32位操作系统和64位操作系统存在兼容性问题. 解决方案: 1.鼠 ...

  9. MySql_安装及简单命令

    一.下载MySql http://dev.mysql.com/downloads/file/?id=461390 版本位5.7.11.0.msi,32位的,但是该版本在64位机器上也可以使用 二.安装 ...

  10. C++多重继承二义性解决

    1. 什么是多重继承的二义性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A{ public:     void f(); }   class B{ pu ...