简介:

  今天我想谈谈如何使用抽象类,以及抽象类真正的威力。本文将结合具体业务来说明如何使用抽象类。

业务简述:

  本人目前只接触过PMS(物业管理系统),公司主要业务的是美国的租房业务。由于美国租房和中国租房在后台可能有点差别,本文不做叙述。下面我们直入主题。

  当用户点击租房之后,我们是要创建一个订单,而在创建订单的时候,需要做很多事,本文只做一个简化版的,避免偏离主题。当创建订单时,需要做以下几件事:

    1.Available 检查是否可用
    2.MinDay 检查 最小入住天数是否匹配
    3.Check in/Check out 检查入住时间和离开时间是否匹配

    4.quote 计算价格。

  而针对前三中,只是判断该房可不可以租。而且有可能以后还会加入其它规则,如果把它们写在一起也是可以的,但不利于扩展。下面看下我如何使用abstract类来实现他的扩展性:

  1.第一步,创建以下类

    1.1 创建类 OrderAddDTO.cs    

    public class OrderAddDTO
{
/// <summary>
/// 物业Id
/// </summary>
public Guid PropertyId { get; set; }
/// <summary>
/// 入住时间
/// </summary>
public DateTime CheckInDate { get; set; }
/// <summary>
/// 离开时间
/// </summary>
public DateTime CheckOutDate { get; set; } //TODO:其它信息
}

     1.2 创建抽象类 PropertyValidAbstract.cs

    public abstract class PropertyValidAbstract
{
protected PropertyValidAbstract _baseValid;
public void SetNext(PropertyValidAbstract BaseValid)
{
this._baseValid = BaseValid;
}
public static string ErrorMsg { get; set; }
public abstract bool IsValid(OrderAddDTO dto);
}

      1.3 创建Available 验证类:AvailableValid,并继承自PropertyValidAbstract

    public class AvailableValid : PropertyValidAbstract
{
public override bool IsValid(OrderAddDTO dto)
{
//TODO:取出该property(物业)的 Available //if (计算该物业在dto.CheckInDate-dto.CheckOutDate时间内是否可用)
//{
//不可用,则对ErrorMsg赋值,并返回false;
//TODO:具体实现
//} //如果没有下一步验证了,则返回true
if (this._baseValid == null)
{
return true;
} //如果可用,则进入下一个验证
return this._baseValid.IsValid(dto); }
}

      1.4 创建MinDay 验证类MinDayValid.cs,并继承自PropertyValidAbstract

    public class MinDayValid : PropertyValidAbstract
{
public override bool IsValid(OrderAddDTO dto)
{
//TODO:取出该property(物业)的 MinDay规则 //模拟minday规则,具体的minday比这个复杂多了
var checkDays = (dto.CheckOutDate - dto.CheckInDate).Days + 1;
if (checkDays<3)
{
ErrorMsg = "stay at least 3 days";
return false;
} //如果没有下一步验证了,则返回true
if (this._baseValid == null)
{
return true;
} //如果满足,则进入下一个验证
return this._baseValid.IsValid(dto);
}
}

      1.5 创建CheckIn/Out验证类:CheckInOutDateValid.cs,并继承自PropertyValidAbstract

    public class CheckInOutDateValid : PropertyValidAbstract
{
public override bool IsValid(OrderAddDTO dto)
{ //模拟checkin/checkout规则判断
DayOfWeek checkInWeek = dto.CheckInDate.DayOfWeek;
DayOfWeek checkOutWeek = dto.CheckOutDate.DayOfWeek;
if (checkOutWeek!= DayOfWeek.Saturday||checkInWeek!= DayOfWeek.Tuesday)
{
ErrorMsg = "checkin/out Does not meet the";
return false;
}
//如果没有下一步验证了,则返回true
if (this._baseValid==null)
{
return true;
}
return this._baseValid.IsValid(dto);
}
}

      1.6 最后在创建一个验证配置类:ValidSettings.cs,并继承自PropertyValidAbstract

    public class ValidSettings: PropertyValidAbstract
{public override bool IsValid(OrderAddDTO dto)
{
//先进行AvailableValid
PropertyValidAbstract BaseValid = new AvailableValid();
//在验证MinDayValid
var mindayvalid = new MinDayValid();
BaseValid.SetNext(mindayvalid);
//最后是CheckInOutDateValid
var checkinOutvalid = new CheckInOutDateValid();
mindayvalid.SetNext(checkinOutvalid); return BaseValid.IsValid(dto);
}
}

  2.在控制台模拟:

        static void Main(string[] args)
{
///这个dto,是从客户端传过来的,在这模拟下
OrderAddDTO dto = new OrderAddDTO();
dto.CheckInDate = DateTime.Now;
dto.CheckOutDate = DateTime.Now.AddDays(1); PropertyValidAbstract baseValid = new ValidSettings(); if (baseValid.IsValid(dto)==false)
{
Console.WriteLine(PropertyValidAbstract.ErrorMsg);
}
else
{
//TODO:计算价格
                Console.WriteLine("计算价格");
} Console.ReadKey();
}

  3.运行结果:

    3.1 测试不满足minday规则

    

    3.2 测试都满足

    

  运行结果都没问题,这时候可能客户来需求,你再给我加个maxday(最大入住天数规则)。这时候我们可以这么做:

    1. 新建一个maxday验证类:MaxDayValid.cs,并继承自PropertyValidAbstract

    public class MaxDayValid : PropertyValidAbstract
{
public override bool IsValid(OrderAddDTO dto)
{
//TODO:取出该property(物业)的 MaxDay规则 //模拟maxday规则,具体的maxday比这个复杂多了
var checkDays = (dto.CheckOutDate - dto.CheckInDate).Days + 1;
if (checkDays >300)
{
ErrorMsg = "stay up to 300 days";
return false;
} //如果没有下一步验证了,则返回true
if (this._baseValid == null)
{
return true;
}
return this._baseValid.IsValid(dto);
}
}

    2.修改ValidSettings.cs类

    public class ValidSettings: PropertyValidAbstract
{ public override bool IsValid(OrderAddDTO dto)
{
//先进行AvailableValid
PropertyValidAbstract BaseValid = new AvailableValid();
//在验证MinDayValid
var mindayvalid = new MinDayValid();
BaseValid.SetNext(mindayvalid); //新增一个maxday
var maxdayvalid = new MaxDayValid();
mindayvalid.SetNext(maxdayvalid); //最后是CheckInOutDateValid
var checkinOutvalid = new CheckInOutDateValid();
maxdayvalid.SetNext(checkinOutvalid); return BaseValid.IsValid(dto);
}
}

    3. 我们来看下运行结果:

  

结束语:

  希望我的文章能对你有所帮助,其实以上使用抽象类的例子也是一个设计模式的例子,责任链模式。。关于设计模式不能死记住,得做到“得其意,忘其形”。谢谢观看。

如何使用Abstract类?抽象类的威力的更多相关文章

  1. 事实证明,abstract类除了不能用new实例化和类没什么区别

    abstract类是抽象类,不能够实例化,大家都知道,abstract类往往和接口interface一块儿使用,针对接口中一些公共的方法进行实现,然后实体类去继承抽象类和接口.虽然abstract类不 ...

  2. final方法,abstract方法和abstract类,native方法

    final方法 1.为了确保某个函数的行为在继承过程中保持不变,并且不能被覆盖(override),可以使用final方法. 2.为了效率上的考虑,将方法声明为final,让编译器对此方法的调用进行优 ...

  3. c# 事实证明,abstract类除了不能用new实例化和类没什么区别

    abstract类是抽象类,不能够实例化,大家都知道,abstract类往往和接口interface一块儿使用,针对接口中一些公共的方法进行实现,然后实体类去继承抽象类和接口.虽然abstract类不 ...

  4. Interface与abstract类的区别

    含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象.含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必 ...

  5. Java abstract关键字 抽象类 抽象方法

    用 abstract 修饰的类是抽象类,它不能生成对象 含有抽象方法的类称为抽象类 抽象方法使用 abstract 修饰 抽象类不能直接实例化,只能由子类实例化 举例 abstract class T ...

  6. Java abstract类的基本使用 和 [abstract类实现]打印1000以内的所有素数并输出时间

    笔记: /** 关键字abstract ,实现抽象类,相当于给出类的大纲,子类只管继承,但抽象类不可被实例化! * 1.抽象方法只保留方法的功能,而具体的执行,交给继承抽象类的子类,由子类重写所有的抽 ...

  7. [转]C#中的abstract 类和方法

    转:https://www.cnblogs.com/zzy2740/archive/2005/09/20/240808.html C#中的abstract类不能被实例化,他只提供其他类的继承的接口 u ...

  8. java中abstract关键字(抽象类)

    需求 当父类某个方法,需要声明,但是又不确定如何实现时,可以用抽象方法,那么这个类就是抽象类 例如:父类是一个动物类,父类里面有很多方法,其中有一个方法是吃食物,但是不知道吃什么,需要子类继承的时候重 ...

  9. day27 多态 多继承 接口类 抽象类

    简单来说:多态就是指一个相同的方法名在不同的对象调用的时候实现一样或者不一样的方法实例1: 动物类有个方法 "嚎叫" 狗类也有个方法 "嚎叫" 猫类继承了动物类 ...

  10. python开发面向对象基础:接口类&抽象类&多态&钻石继承

    一,接口类 继承有两种用途: 一:继承基类的方法,并且做出自己的改变或者扩展(代码重用) 二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实 ...

随机推荐

  1. ELasticsearch忘记密码后重置超级用户密码

    创建一个临时的超级用户TestSuper: [root@cfeea elasticsearch]# ./bin/elasticsearch-users useradd TestSuper -r sup ...

  2. WMS 相比于 ERP 系统有哪些优势?

    WMS与ERP系统是两个不同的系统,不存储优势的比较!WMS是仓库管理系统(Warehouse Management System) 的缩写,ERP是Enterprise Resource Plann ...

  3. Node.js(四)json

    npm init -y(初始化项目) npm install express(引入express) npx express-generator -e(自动生成模板.添加对 ejs 模板引擎的支持) n ...

  4. Docker | 部署nginx服务

    容器时相互隔离的,docker启动的nginx是容器内的服务,不影响我原先服务器上的nginx服务,小伙伴们可大胆尝试 本篇实在linux环境下操作的,主要目的是夺人眼目,对使用Docker部署服务尝 ...

  5. Netty 学习(十):ChannelPipeline源码说明

    Netty 学习(十):ChannelPipeline源码说明 作者: Grey 原文地址: 博客园:Netty 学习(十):ChannelPipeline源码说明 CSDN:Netty 学习(十): ...

  6. 【NOI2016】 循环之美 题解

    Solution 由数论基础知识 答案即为$$\sum_{i = 1}^n\sum_{j = 1}^m[i \perp j][j \perp k]$$ 莫反套路可化为$$\sum_{d = 1}\mu ...

  7. 『现学现忘』Git基础 — 35、Git中删除文件

    目录 1.删除文件说明 2.删除文件操作 (1)仅删除暂存区的文件 (2)完全删除文件 3.本文用到的命令总结 1.删除文件说明 在Git工作目录中要删除某个文件,首先要清楚该文件所处的状态. 若要是 ...

  8. Java程序员必会Synchronized底层原理剖析

    synchronized作为Java程序员最常用同步工具,很多人却对它的用法和实现原理一知半解,以至于还有不少人认为synchronized是重量级锁,性能较差,尽量少用. 但不可否认的是synchr ...

  9. OpenAPI 接口幂等实现

    OpenAPI 接口幂等实现 1.幂等性是啥? 进行一次接口调用与进行多次相同的接口调用都能得到与预期相符的结果. 通俗的讲,创建资源或更新资源的操作在多次调用后只生效一次. 2.什么情况会需要保证幂 ...

  10. 利用nginx自带的反向代理以及轮询功能实现应用的负载均衡

    针对中间件部署的应用(war包),可使用nginx自带的反向代理以及轮询功能,实现应用的负载均衡. 一.架构图 二.环境准备 准备2套环境,如19.1.0.18:7001,19.1.0.16:7001 ...