抽象工厂模式
抽象工厂模式表示只需定义一个接口或抽象类来创建相关(或依赖)对象系列,但不指定它们的具体子类。这意味着抽象工厂让一个类返回一个类工厂。所以,这就是抽象工厂模式比工厂模式高一级的原因。
抽象工厂模式也称为Kit。
抽象工厂模式的优势
- 抽象工厂模式将客户端代码与具体(实现)类隔离开来。
- 它简化了对象系列的交换。
- 它促进了对象之间的一致性。
抽象工厂模式的使用
- 当系统需要独立于其对象的创建、组合和表示方式时。
- 当相关对象系列必须一起使用时,则需要强制执行此约束。
- 当您想提供一个不显示实现而只显示接口的对象库时。
- 当系统需要配置多个对象系列中的一个时。
抽象工厂模式的 UML
- 我们将创建一个Bank 接口和一个Loan 抽象类以及它们的子类。
- 然后我们将创建AbstractFactory类作为下一步。
- 然后我们将创建扩展AbstractFactory 类的具体类BankFactory和LoanFactory
- 之后,AbstractFactoryPatternExample类使用FactoryCreator来获取AbstractFactory类的对象。
- 仔细看下图:
unit AbstractFactoryImpl;
interface
uses System.Math, System.SysUtils;
type
IBank = interface
['{AE63EBF9-D8E5-49CA-A01F-CE6DB3C1380C}']
function getBankName: String;
end;
THDFC = class(TInterfacedObject, IBank)
private
BNAME: string;
public
constructor create;
function getBankName: String;
end;
TICICI = class(TInterfacedObject, IBank)
private
BNAME: string;
public
constructor create;
function getBankName: String;
end;
TSBI = class(TInterfacedObject, IBank)
private
BNAME: string;
public
constructor create;
function getBankName: String;
end;
TLoan = class abstract
protected
FRate: Extended;
public
procedure getInterestRate(Arate: Extended);virtual;abstract;
procedure calculateLoanPayment(Aloanamount: Extended; Ayears: integer);
end;
THomeLoan = class (TLoan)
public
procedure getInterestRate(Arate: Extended);override;
end;
TBussinessLoan = class (TLoan)
public
procedure getInterestRate(Arate: Extended);override;
end;
TEducationLoan = class (TLoan)
public
procedure getInterestRate(Arate: Extended);override;
end;
TAbstractFactory = class abstract
public
function getBank(Abank: String ): IBank ;virtual;abstract;
function getLoan(Aloan: String ): TLoan ;virtual;abstract;
end;
TBankFactory = class (TAbstractFactory)
public
function getBank(Abank: String ): IBank ;override;
function getLoan(Aloan: String ): TLoan ;override;
end;
TLoanFactory = class (TAbstractFactory)
public
function getBank(Abank: String ): IBank ;override;
function getLoan(Aloan: String ): TLoan ;override;
end;
TFactoryCreator = class
public
class function getFactory(Achoice: String ): TAbstractFactory ;static;
end;
implementation
function TLoanFactory.getBank( Abank : String):IBank;
begin
Result := nil;
end;
class function TFactoryCreator.getFactory( Achoice : String):TAbstractFactory;
begin
if Achoice = 'Bank' then
begin
Result := TBankFactory.Create();
end
else
if Achoice = 'Loan' then
begin
Result := TLoanFactory.Create();
end
else
Result := nil;
end;
function TLoanFactory.getLoan( Aloan : String):TLoan;
begin
if Aloan = '' then
begin
Result := nil;
end
else
if Aloan = 'Home' then
begin
Result := THomeLoan.Create();
end
else
if Aloan = 'Business' then
begin
Result := TBussinessLoan.Create();
end
else
if Aloan = 'Education' then
begin
Result := TEducationLoan.Create();
end
else
Result := nil;
end;
//=========================TBankFactory==============================
function TBankFactory.getLoan(Aloan: String ): TLoan ;
begin
Exit(nil);
end;
function TBankFactory.getBank( Abank : String):IBank;
begin
if Abank.Empty = '' then
begin
Result := nil;
end;
if Uppercase(Abank) = ('HDFC' )then
begin
Result := THDFC.create();
end
else
if(Abank = 'ICICI') then
begin
Result := TICICI.create();
end
else
if(Abank = 'SBI') then
begin
Result := TSBI.create();
end
else
Result := nil;
end;
procedure TEducationLoan.getInterestRate(Arate: Extended);
begin
Frate := Arate;
end;
procedure TBussinessLoan.getInterestRate(Arate: Extended);
begin
Frate := Arate;
end;
procedure THomeLoan.getInterestRate(Arate: Extended);
begin
Frate := Arate;
end;
procedure TLoan.calculateLoanPayment( Aloanamount : Extended; Ayears : integer);
var
EMI : Extended;
n : integer;
begin
{
to calculate the monthly loan payment i.e. EMI
rate := annual interest rate/12*100;
1year := 12 months.
so, n=years*12;
}
n := Ayears*12;
Frate := Frate/1200;
EMI := ((Frate*power((1+Frate),n))/((power((1+Frate),n))-1))*Aloanamount;
writeln('your monthly EMI is "+ EMI +" for the amount"+loanamount+" you have borrowed');
end;
constructor THDFC.create;
begin
BNAME := 'HDFC BANK';
end;
function THDFC.getBankName: String ;
begin
result := BNAME;
end;
//==============================================================
constructor TICICI.create;
begin
BNAME := 'ICICI BANK';
end;
function TICICI.getBankName: String ;
begin
result := BNAME;
end;
//===================================================================
constructor TSBI.create;
begin
BNAME := 'SBI BANK';
end;
function TSBI.getBankName: String ;
begin
result := BNAME;
end;
end.