服务方法兼容性适配
1、准备
还是上面的那个示例,如果消费者Web Service需要的不是一整票报价,而是报价单中某一票商品的内容,那么调用时他除了id、company两个参数外,还需要提供对应QuoteItem的productId,因此需要进行服务方法的适配。
图8:服务方法兼容性适配
参考上例和上图,定义作为Adaptee的生产者Web Service和作为客户程序的消费者 Web Service。测试报价单数据如下:
//XML
<?xml version="1.0" encoding="UTF-8"?>
<Quote Company="VisionTask" Id="Quote 2007-07-18"
xsi:schemaLocation="http://www.visionlogic.com/trade quote.xsd"
xmlns="http://www.visionlogic.com/trade"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<QuoteItem ProductId="19" QuantitiveInStock="1750" Price="3.14"/>
<QuoteItem ProductId="312" QuantitiveInStock="10" Price="3000"/>
</Quote>
2、根据消费者Web Service的需要,定义对应的Service Adapter
//C# ITarget
using System.Xml;
namespace VisionTask.Training.ServicePattern.UtilityService.MethodAdapter
{
/// <summary>
/// 消费者Web Service 需要的接口。
/// </summary>
public interface ITarget
{
XmlNode GetItem(string company, string id, string productId);
}
}
//C# QuoteServiceMethodAdapter
using System.Xml;
using VisionTask.Training.ServicePattern.Common.Xml;
using VisionTask.Training.ServicePattern.ServiceAdapter;
namespace VisionTask.Training.ServicePattern.UtilityService.MethodAdapter
{
public class QuoteServiceMethodAdapter : IServiceAdapter, ITarget
{
/// <summary>
/// 实现一般性IServiceAdapter 的要求。
/// </summary>
public virtual string Name { get { return "ServiceMethod"; } }
/// <summary>
/// 实现消费者 Web Service 需要的接口。
/// </summary>
public XmlNode GetItem(string company, string id, string productId)
{
XmlDocument doc = (new ProducerServiceM()).GetQuote(company, id);
if ((doc == null) || (!doc.HasChildNodes)) return null;
string xPath = "/Quote/QuoteItem[@ProductId=" + productId + "]";
System.Diagnostics.Trace.WriteLine(xPath);
XmlNode node = doc.SelectSingleNode(xPath);
return node;
}
}
}
3、借助抽象的 Service Adapter,实现消费者 Web Service
//C#
using System;
using System.Xml;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace VisionTask.Training.ServicePattern.UtilityService.MethodAdapter
{
/// <summary>
/// 客户Web Service。
/// 它继续封装对外的服务,使用时可以根据他获得某公司提供的报价单中,
/// 具体某项商品的价格。
/// </summary>
[WebService(Namespace = "http://www.visionlogic.com/trade")]
public class ConsumerServiceM : System.Web.Services.WebService
{
[WebMethod]
public double GetPrice(string company, string id, string productId)
{
ITarget target = new QuoteServiceMethodAdapter();
XmlNode node = target.GetItem(company, id, productId);
if (node == null) throw new NullReferenceException();
return Convert.ToDouble(node.Attributes["Price"].Value);
}
}
}
其他说明
对于第三种“封装性适配”则是上述两种方式的组合:
•数据的转换。
•方法的适配。
•在Service Adapter中嵌入额外的逻辑。
•而双向适配则是双方各自定义自己的适配器。