使用面向对象重构之-使用接口抽象完成不同维度的扩展
2017-03-02 00:11
369 查看
本文承接上文 使用面向对象重构之-使用接口完成行为抽象。
这次要面对的需求变化是报销流程不仅与员工类别相关,也与报销种类相关,每个报销种类的流程要去不同部门办理,流程差别较大,需要分别扩展。
车费分为打车费和公共交通;打车费需要小票而公共交通则不需要;加班可以报销晚餐;出差的人可以有出差补助,不同城市也有不同的流程。为了让代码体系适应这个需求,就需要引入新的抽象,让代码依赖这个新的抽象体系。
以下代码为之前的实现:
我们只是根据员工种类提供不同报销逻辑的provider,显然已经不够。现在需要进一步对抽象进行调整为:
接口和类接口基本定义好了。这样就完成了不同报销类别的横向扩展,可是出现了一个问题,staff种类变多了,创建责任就需要统一化,否则对象创建的位置不一,会降低程序的内聚性。这也是Information Expert原则所指出的,信息集中化。下一部分就会着重介绍统一对象创建的位置,以及提高程序内聚性的重要性。
这几个例子是比较极端的需求变更,通常建议project一开始就要规划清楚接口和类的结构,前期需求与代码结构的映射越匹配,所创建的抽象也就越稳定。
这次要面对的需求变化是报销流程不仅与员工类别相关,也与报销种类相关,每个报销种类的流程要去不同部门办理,流程差别较大,需要分别扩展。
车费分为打车费和公共交通;打车费需要小票而公共交通则不需要;加班可以报销晚餐;出差的人可以有出差补助,不同城市也有不同的流程。为了让代码体系适应这个需求,就需要引入新的抽象,让代码依赖这个新的抽象体系。
以下代码为之前的实现:
public interface IClaim { void Claim(); } public class StaffClaimProvider : IClaim { public void Claim() { throw new NotImplementedException(); } } public class SalesClaimProvider : IClaim { public void Claim() { throw new NotImplementedException(); } }
我们只是根据员工种类提供不同报销逻辑的provider,显然已经不够。现在需要进一步对抽象进行调整为:
public interface ITransportClaim{ void ClaimTransport(); } public class TaxiClaimProvider : ITransportClaim{ public void ClaimTransport(){ ... } } public class PublicTrafficClaimProvider : ITransportClaim{ public void ClaimTransport(){ ... } } public interface IOverTimeFoodClaim{ void ClaimFood(); } public class WorkOverTimeFoodClaimDefaultProvider: IOverTimeFoodClaim{ public void ClaimFood(){ ... } } public class WorkOverTimeFoodClaimMidnightProvider: IOverTimeFoodClaim{ public void ClaimFood(){ ... } } public interface ITravelClaim{ void ClaimTravel(); } public class TravelSameCountryClaimProvider:ITravelClaim{ public void ClaimTravel(); } public interface CrossCountryClaimProvider:ITravelClaim{ public void ClaimTravel(); } public class StaffBase{ ... } public class LocalStaff :StaffBase{ public Staff(ITransportClaim transportClaimProvider){ ... } } public class OTStaff: LocalStaff{ public class OTStaff(ITransportClaim transportClaimProvider, IOverTimeFoodClaim otClaimProvider): base(transportClaimProvider){ ... } } public class TravelStaff :StaffBase{ public class TravelStaff(ITravelClaim travelClaimProvider){ } }
接口和类接口基本定义好了。这样就完成了不同报销类别的横向扩展,可是出现了一个问题,staff种类变多了,创建责任就需要统一化,否则对象创建的位置不一,会降低程序的内聚性。这也是Information Expert原则所指出的,信息集中化。下一部分就会着重介绍统一对象创建的位置,以及提高程序内聚性的重要性。
这几个例子是比较极端的需求变更,通常建议project一开始就要规划清楚接口和类的结构,前期需求与代码结构的映射越匹配,所创建的抽象也就越稳定。
相关文章推荐
- 使用面向对象重构之-使用接口完成行为抽象
- 使用面向对象重构之-继承中的抽象—模板方法
- 使用面向对象重构之-把抽象控制在一处:提高内聚性
- Java基础知识:面向对象-抽象、接口、内部类
- 避免代码冗余,使用接口和泛型重构Java代码
- 使用attribute + 扩展方法完成 enum中field的信息映射
- artDialog对话框组件使用心得,其功能完善,接口友好,提供多套皮肤,支持iframe跨页面扩展
- 使用Eclipse中提供的Refactor(重构)工具提取接口
- SQL Server扩展事件(Extended Events)-- 使用扩展事件不同目标示例
- c#3.0 中使用扩展方法来扩展接口
- SSM项目从零开始到入门007-使用接口完成增删改查操作
- PHP面向对象:接口与抽象方法
- Spring MVC 使用支付宝接口完成在线支付的示例代码
- 什么时候使用接口?什么时候使用抽象?选择Java接口还是抽象类 (转)
- 什么时候使用接口?什么时候使用抽象?选择Java接口还是抽象类
- 使用嵌套类来清晰化类接口,分离扩展操作和扩展查询。
- php扩展开发,不同扩展使用相同函数名
- 使用接口实现功能扩展
- 一步步学spark之一scala中面向对象的不同构造器使用2.1
- 使用Eclipse完成经典的重构