接口的功能类似抽象类, 通常定义一套通用的方法,但是在各实现类中有不同的实现方式。
以下几句来源于网络整理:
(1)接口中只有方法、属性,没有字段。所以接口中的属性存取都必须通过方法。
(2)接口中的方法只有声明,没有实现。实现在类中完成。
(3)接口中的方法没有作用域。都是公开的,但是在类中则放到不同作用域。
(4)接口中的方法没有修饰字。可以认为它们都是抽象的。
(5)不能创建接口实例,要使用接口,必须在类中实现,通过类调用接口的方法。
(6)在类中必须声明和实现接口的所有方法。不像类继承中可以选择。
(7)接口中的方法在类中实现时,可以加virtual/dynamic、abstract修饰,从而在子类中可以实现覆盖。
以上内容在下方代码中一一实现(第七条没弄)
开发中经常遇到某某平台的对接什么的,某某消费机对接什么的,其实大致操作流程是差不多的,发送支付请求,发送查询请求,发送退款请求等, 简而言之,接口定义的一套通用的方法.
界面演示截图:
工程文件DelphiInterface.dpr代码:
program DelphiInterface;
uses
Forms,
uFrmMain in 'uFrmMain.pas' {FrmMain},
uPayInterface in 'intf\uPayInterface.pas',
uCloudPay_A in 'public\uCloudPay_A.pas',
uCloudPay_B in 'public\uCloudPay_B.pas',
uPay in 'public\uPay.pas';
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TFrmMain, FrmMain);
Application.Run;
end.
接口单元uPayInterface.pas代码:
unit uPayInterface;
interface
uses
Windows;
type
//支付接口 通用的有本地初始化 支付请求 查询请求
IPay= interface(IInterface)
['{F105EA82-976D-4CC8-9315-F3C43055EACF}'] //Ctrl+ Shift+ G 自动生成
procedure init; //初始化
function getClassname: string; //获取类名
function Pay(const sIn: string; out sOut: string): Integer; //支付
function Query(const sIn: string; out sOut: string): Integer; //查询
end;
implementation
end.
实现类uCloudPay_A.pas代码:
unit uCloudPay_A;
interface
uses
uPayInterface;
type
TCloudPay_A= class(TInterfacedObject, IPay)
private
procedure init; //初始化
public
constructor Create;
destructor Destroy; override;
function getClassname: string; //获取类名
function Pay(const sIn: string; out sOut: string): Integer; //支付
function Query(const sIn: string; out sOut: string): Integer; //查询
end;
implementation
{ TCloudPay_A }
constructor TCloudPay_A.Create;
begin
init; //做一些初始化操作 比如参数读取 或 参数动态创建
end;
destructor TCloudPay_A.Destroy;
begin
//可能有些参数需要释放
inherited;
end;
function TCloudPay_A.getClassname: string;
begin
Result:= 'TCloudPay_A';
end;
procedure TCloudPay_A.init;
begin
//各支付平台有各子的配置参数 可在这里读取本地配置文件
end;
function TCloudPay_A.Pay(const sIn: string; out sOut: string): Integer;
begin
//
Result:= 200;
end;
function TCloudPay_A.Query(const sIn: string; out sOut: string): Integer;
begin
//
Result:= 200;
end;
end.
实现类uCloudPay_B.pas代码:
unit uCloudPay_B;
interface
uses
uPayInterface;
type
TCloudPay_B= class(TInterfacedObject, IPay)
private
procedure init; //初始化
public
constructor Create;
destructor Destroy; override;
function getClassname: string; //获取类名
function Pay(const sIn: string; out sOut: string): Integer; //支付
function Query(const sIn: string; out sOut: string): Integer; //查询
end;
implementation
{ TWXPay }
constructor TCloudPay_B.Create;
begin
init; //做一些初始化操作 比如参数读取 或 参数动态创建
end;
destructor TCloudPay_B.Destroy;
begin
//可能有些参数需要释放
inherited;
end;
function TCloudPay_B.getClassname: string;
begin
Result:= 'TCloudPay_B';
end;
procedure TCloudPay_B.init;
begin
//各支付平台有各子的配置参数 可在这里读取本地配置文件
end;
function TCloudPay_B.Pay(const sIn: string; out sOut: string): Integer;
begin
//
Result:= 200;
end;
function TCloudPay_B.Query(const sIn: string; out sOut: string): Integer;
begin
//
Result:= 200;
end;
end.
支付单元uPay.pas代码:
unit uPay;
interface
uses
SysUtils, uPayInterface, uCloudPay_A, uCloudPay_B;
type
TPay = class(TObject)
private
IPayObj: IPay;
protected
//
public
constructor Create(iType: Integer);
destructor Destroy; override;
function getPayObjClass: string; //获取IPayObj的创建类名
function Pay(const cPay: Currency; out sOut: string): Integer; //支付
function Query(const sOrderId: string; out sOut: string): Integer; //查询
end;
implementation
{ TPay }
constructor TPay.Create(iType: Integer);
begin
//根据外部传入的平台类型 创建不同的对象
case itype of
0: //TCloudPay_A
begin
IPayObj:= TCloudPay_A.Create;
end;
1: //TCloudPay_B
begin
IPayObj:= TCloudPay_B.Create;
end;
end;
end;
destructor TPay.Destroy;
begin
//接口对象用完会自动释放 也可以通过设置nil主动释放
if Assigned(IPayObj) then
IPayObj:= nil; //可以这样主动释放接口; 同时拥有它的类也会释放
inherited;
end;
function TPay.getPayObjClass: string;
begin
Result:= IPayObj.getClassname;
end;
function TPay.Pay(const cPay: Currency; out sOut: string): Integer;
var
sIn: string;
begin
//sIn:= ...
Result:= IPayObj.Pay(sIn, sOut);
end;
function TPay.Query(const sOrderId: string; out sOut: string): Integer;
var
sIn: string;
begin
//sIn:= ...
Result:= IPayObj.Query(sIn, sOut);
end;
end.
窗体单元uFrmMain.pas代码:
unit uFrmMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, uPayInterface, uPay;
type
TFrmMain = class(TForm)
RadioGroup1: TRadioGroup;
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
Button9: TButton;
Button10: TButton;
Button11: TButton;
Button12: TButton;
procedure Button9Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
procedure Button11Click(Sender: TObject);
procedure Button12Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
FPay_A: TPay;
FPay_B: TPay;
FPay: TPay;
end;
var
FrmMain: TFrmMain;
implementation
{$R *.dfm}
procedure TFrmMain.Button10Click(Sender: TObject);
var
sOut: string;
begin
if Assigned(FPay) then
begin
FPay.Pay(0.01, sOut);
ShowMessage(FPay.getPayObjClass+ ' Pay');
end;
end;
procedure TFrmMain.Button11Click(Sender: TObject);
var
sOut: string;
begin
if Assigned(FPay) then
begin
FPay.Query('100011011020', sOut);
ShowMessage(FPay.getPayObjClass+ ' Query');
end;
end;
procedure TFrmMain.Button12Click(Sender: TObject);
begin
if Assigned(FPay) then
FreeAndNil(FPay);
end;
procedure TFrmMain.Button9Click(Sender: TObject);
var
iType: Integer;
begin
iType:= 0;
if RadioButton2.Checked then
iType:= 1;
//iType 可以通过本地ini文件配置或其它配置读取
if not Assigned(FPay) then
FPay:= TPay.Create(iType);
end;
end.
在uPay.pas中,定义了IPayObj, TPay.Create方法通过传入的参数iType,创建不同的实现类实例, 通过这种方式, 就不用去分别定义TCloudPay_A,TCloudPay_B的对象,就一个IPayObj就可以了。 由此,没有去测试实现多接口,如果测试的话,就不能像这样定义一个统一的IPayObj入口了。
水平有限,了解不深,后续跟进.