在《大话设计模式》中大鸟和小菜是通过姚明刚加入火箭队时候英文不好,需要一个中间翻译来沟通,就类似于软件设计中的适配器模式一样,引入话题的。Adapter,将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。
对于这个模式我是身有体会,因为在曾经开发电子商务系统的时候,需要同客户的淘宝网店、客户的ERP系统数据建立数据交互,然后淘宝接口中取的数据有淘宝自己的数据格式,与淘宝的数据交互主要是订单信息和订单收货人信息,而同客户ERP交互的主要是基础库信息,如产品、门店等信息。自身的系统同样建立了会员、门店、产品、订单等信息表,也同样建立由此展开的业务逻辑类、数据Model、以及访问接口类。这样一来的话,以订单信息为例,淘宝接口返回的数据有订单数据的Model,ERP实体门店订单数据的Model和电商自身的订单Model又是截然不同的,而由此导致的订单业务逻辑操作也是不同的。
就以这个应用为例,我们以电商为核心,因为这个是需要继续完善和拓展的,而淘宝和ERP我们都暂时认为是需要接入的系统,那么如何在自己的电商系统中完美无缝的连接入淘宝、ERP的数据,以及如何完整没有隔阂的访问这两类订单数据呢。
实体类代码:
public class MemberInfo { public string MmbrInfoID { get; set; } public string MmbrInfoName { get; set; } } public class Taobao_TransactionH { public string TransHID { get; set; } public string StoreCode { get; set; } public string Receiver_name { get; set; } } public class ERPDD { public string DDID { get; set; } public string HYID { get; set; } } public class Order_Info { public string OrderID { get; set; } public string MmbrInfoID { get; set; } public MemberInfo MmbrInfo { get; set; } public Order_Info() { } }
初步的思路是这样的,电商作为本地系统更新,淘宝和ERP的数据导入中间库,而后在中间库中形成自己的访问数据模式,而涉及到订单数据的对外接口,我们可以统一使用适配器模式,将淘宝的订单数据、ERP实体店的订单数据转化为本地电商的数据Model和业务实现类。
由于适配器的实现,说到底就是若干各类组成的,为完成这样一个耦合度的设计,在这个实例中说白了就是我需要将TaoBao和ERP订单操作适用于Order,那么就需要针对TaoBao和ERP各写一个适配器类,那么实现起来不同的程序员或许有不同实现方式,我,所以,遇到这种统一规范的事情,第一想到的就是接口或抽象类。
定义IOrderServiceAdapter接口,就此在系统架构中立一个永垂不朽的钉子,我的订单适配器都必须实现该接口,别的不认!
接口中定义了一个方法,返回类型为Order_Info为最终同电商的类型匹配,参数为一个类型Object,这里如果想继续复杂点,可以不用Object,使用泛型T实现。
代码实现:
public interface IOrderServiceAdapter { Order_Info GetOrderInfoByOrderID(object obj, AdapterType at); }
实现这个接口的就是为所有接入的订单信息,做准备的,我们这里比如的淘宝订单、ERP订单,若干天后,我们出现了京东的订单,再若干天后我们又出现了拍拍商城的订单,只要实现了这个接口,就能通自己电商系统中的订单信息进行适配。所以在系统中我加了第二个参数AdapterType,枚举类型,为就是分辨出不同来源的订单类型,进行转换,当然这里其实我们可以用工厂模式来进行处理,后续再细聊。
枚举类型实现代码:
public enum AdapterType { Taobao_TransactionH = 0, ERPDD = 1 }
适配器实现代码:
public class OrderServiceAdapter : IOrderServiceAdapter { public virtual Order_Info GetOrderInfoByOrderID(object obj, AdapterType at) { Order_Info order = new Order_Info(); switch (at) { case AdapterType.ERPDD: ERPDD erp = obj as ERPDD; order.OrderID = erp.DDID; break; case AdapterType.Taobao_TransactionH: Taobao_TransactionH th = obj as Taobao_TransactionH; order.OrderID = th.TransHID; break; ; } return order; } }
好,由此整个大的框架我们就确定了,运行代码:
class Program { static void Main(string[] args) { Taobao_TransactionH tModel = new Taobao_TransactionH(); tModel.TransHID = Guid.NewGuid().ToString() + "_TaoBao"; ERPDD eModel = new ERPDD(); eModel.DDID = Guid.NewGuid().ToString() + "_ERP"; OrderServiceAdapter osAdapter = new OrderServiceAdapter(); Order_Info orderH= osAdapter.GetOrderInfoByOrderID(tModel, AdapterType.Taobao_TransactionH); Order_Info orderE=osAdapter.GetOrderInfoByOrderID(eModel, AdapterType.ERPDD); Console.WriteLine(orderH.OrderID); Console.WriteLine(orderE.OrderID); } }
运行结果:
附上我的源代码:https://files.cnblogs.com/aspnetdream/ModelPro_Adapter.rar
由此我们可以看出,将三个完全不搭的类型,搭到了一起,统一到了Order_Info的类型,我想上述的思想和思路可能,很多人一看都懂,也没有太多花哨的代码,但,我们确实使用到了设计模式,其实设计模式并没有那么高深,当然想用好,想用精可能高深的代码还真需要花功夫。
最后,在说说在《大话设计模式》中其实也指出来了,这个模式并不是事前模式,他更多的看做是一种修复模式,我们可以在实例中看到,其实,这个在愈合三个系统,如果是一般的设计一个全新的系统,大可不必使用着这个找兼容的模式,给一个新系统设计架构的时候,我们在设计之初就应该考虑兼容性,所以模式这篇中用扁鹊医病来形象的说明了这个问题,将病症防微杜渐才是真的高明的医生。