简介:

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

业务简述:

  本人目前只接触过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. gitlab cicd流水线语法

    流水线语法有哪些? 流水线参数列表 Keyword Description script 运行的Shell命令或脚本. image 使用docker映像. services 使用docker服务映像. ...

  2. flask+gunicorn+nginx部署

    安装nginx和gunicorn yum install nginx pip3 install gunicorn flask项目配置 #main.py from flask import Flask ...

  3. PAT (Basic Level) Practice 1026 程序运行时间 分数 15

    要获得一个 C 语言程序的运行时间,常用的方法是调用头文件 time.h,其中提供了 clock() 函数,可以捕捉从程序开始运行到 clock() 被调用时所耗费的时间.这个时间单位是 clock ...

  4. Linux Subsystem For Android 11!适用于Debian GNU/Linux的Android子系统,完美兼容ARM安卓软件!

    本文将讲述如何在Debian Stable 系统安装一个Android 11子系统,并且这个子系统带有Houdini可以兼容专为移动设备开发的ARM软件.在root权限下,编辑/etc/apt/sou ...

  5. 对循环神经网络参数的理解|LSTM RNN Input_size Batch Sequence

    在很多博客和知乎中我看到了许多对于pytorch框架中RNN接口的一些解析,但都较为浅显甚至出现一些不准确的理解,在这里我想阐述下我对于pytorch中RNN接口的参数的理解. 我们经常看到的RNN网 ...

  6. PyCharm安装PyQt5及其工具(Qt Designer、PyUIC、PyRcc)详细教程

    摘要:Qt是常用的用户界面设计工具,而在Python中则使用PyQt这一工具包,它是Python编程语言和Qt库的成功融合.这篇博文通过图文详细介绍在PyCharm中如何完整优雅地安装配置PyQt5的 ...

  7. 220722 T3 石子染色 (背包)

    序列s中的数就是要选的堆的编号,假设要选的有i个石子,这i个染为红色,剩下j个染为蓝色,i+j=x,i=x-j,那么对答案的贡献是|x-2j|.那么只要我们选的有i个石子,贡献就是这么多,所以我们可以 ...

  8. 如何去了解Spring

    对于你想了解的技术 官方总是一个合适的选择 首先,我们所指的Spring 一般指的是Spring Framework,伴随着的时代的进步,Spring全家桶也逐渐完善起来 Spring 1.Why S ...

  9. 什么是ForkJoin?看这一篇就能掌握!

    摘要:ForkJoin是由JDK1.7之后提供的多线程并发处理框架. 本文分享自华为云社区<[高并发]什么是ForkJoin?看这一篇就够了!>,作者: 冰 河. 在JDK中,提供了这样一 ...

  10. .NET API 接口数据传输加密最佳实践

    .NET API 接口数据传输加密最佳实践 我们在做 Api 接口时,相信一定会有接触到要给传输的请求 body 的内容进行加密传输.其目的就是为了防止一些敏感的内容直接被 UI 层查看或篡改. 其实 ...