Ciao,
Sto creando un importatore.
L'importatore deve poter importare sia da db che da api.
NEll'importatore ho 2 classi intermedie che ragruppano una funzionalità specifica dell'importatore(nel mio caso sezione carichi e sezione stress).
Le due classi intermedie devono poter leggere dati sia da db che da api.
quindi avro
classeintermediaCarichibase e
classeintermediaStressbase
e per ognuna di queste
classeintermediaCarichiApi:classeintermediaCarichi base
classeintermediaCarichiDb:classeintermediaCarichib ase
classeintermediaStressApi:classeintermediaStressba se
classeintermediaStressDb:classeintermediaStressbas e
db e api hanno delle proprie funzioni che servono per la lettura,la configurazione ecc.. dei 2 diversi sitemi(db e api)
Sto quindi cercando un modo per ragruppare le 2 classi x db e le 2 classi x api.
e di creare una classe base con tutte le funzioni relative al tipo di lettura usato.
In modo da scrivere una volta sola queste fuunzioni anzichè replicare il codice ,sia per un fatore di refactoring(devo cambiare un funzione base)sia perchè il tipo di input potrebbe cresere (oltre a db e api ad es text o excel ecc..)
Il problema è che queste due classi derivano da una classe base diversa anche se è lo stesso il itpo di lettura.
Ho pensato al factory method ma non ci sono saltato fuori.
Voi come fareste? anche al limite stravolgendo la mia analisi.
ho provato a tentare di utilizzare il pattern gateway che mi stato consigliato:
ad es:
ho questa classe nelle api
void CSapDataLoadIteratorApi::LoadTagLoadsTempConc(tagL oadDataTempLogic* tagData)
{
tagData->strLoadCase = GetStringValueSA(pSALoadCAse,m_nIndex);
tagData->strFrameObj = GetStringValueSA(pSALineName,m_nIndex);
int nIForceMoment = GetIntValueSA(pSATypeForceMoment,m_nIndex);
tagData->strCoordSys = GetStringValueSA(pSACoordSys,m_nIndex);
tagData->dDistA = GetDecimalValueSA(pSADist1,m_nIndex);
tagData->dValOverLA = GetDecimalValueSA(pSAVal1,m_nIndex);
CString strForceMoment;
( (nIForceMoment==1)?strForceMoment="Force" : strForceMoment="Moment" );
tagData->strDir.Format("%d", GetIntValueSA(pSADir,m_nIndex),tagData->strDir);
tagData->strType = strForceMoment;
}
che carica una struttura tagLoadDataTempLogic di questo tipo:
typedef struct LoadDataTempLogic
{
CString strFrameObj,strFrameEl, strLoadCase, strCoordSys, strType, strDir, strJointI;
double dDistA, dDistB, dValOverLB, dValOverLA;
}tagLoadDataTempLogic;
la funzione GetDecimalValueSA è comune a tutte le classi api e ritorna un valore dato un SAFEARRAY e un indice
la funzione:
void CSapDataLoadIteratorApi::LoadTagLoadsTempGravity(t agLoadDataTempLogic * loadDataTemp, double * dMultiplierX ,double * dMultiplierY ,double * dMultiplierZ , double * dLength ,double * dArea,double * dUnitWeight,CString *strSection,CString *PointI,CString *PointJ)
{
loadDataTemp->strLoadCase = GetStringValueSA(pSALoadCAseGrav,m_nIndex);
CString strDir ="Gravity";
loadDataTemp->strCoordSys = GetStringValueSA(pSACoordSysGrav,m_nIndex);
/*leggo grazie al join con la tabella connectivity joint di
inizio del beam , uilizzata nella funzione calclilj.*/
loadDataTemp->strCoordSys = GetStringValueSA(pSALoadCAseGrav,m_nIndex);
loadDataTemp->strFrameObj = GetStringValueSA(pSALineNameGrav,m_nIndex);
*dMultiplierX = GetDecimalValueSA(pSAXGrav,m_nIndex);
*dMultiplierY = GetDecimalValueSA(pSAYGrav,m_nIndex);
*dMultiplierZ = GetDecimalValueSA(pSAZGrav,m_nIndex);
BSTR strSectionOut;
BSTR strSectionAuto;
BSTR strMissing;
long nMissing = 0;
_bstr_t strEmpty_T;
_bstr_t strNameSection;
strEmpty_T = "";
double dMissing = 0;
// carico una stringa vuota nella BSTR
strSectionOut = strEmpty_T.copy();
strSectionAuto = strEmpty_T.copy();
strMissing = strEmpty_T.copy();
bstr_t strFrameObj=bstr_t(loadDataTemp->strFrameObj);
HRESULT hr = m_pSapModel->FrameObj->GetSection(strFrameObj,&strSectionOut,&strSection Auto);
strNameSection = bstr_t(strSectionOut);
*strSection = CString(strNameSection.GetBSTR());
BSTR bstrPointI;
BSTR bstrPointJ;
bstrPointI = strEmpty_T.copy();
bstrPointJ = strEmpty_T.copy();
hr = m_pSapModel->FrameObj->GetPoints(strFrameObj,&bstrPointI,&bstrPointJ);
*PointI = CString(bstrPointI);
*PointJ = CString(bstrPointJ);
}
usa anche lei la funzione GetDecimalValueSA e GetStringValueSA e ritorna in out vari dati (loaddatatemp,dMultiplierX ecc...)
ecco se ho ben capito devo creare un wrapper attorno alla classe CSapDataLoadIteratorApi e a queste due funzioni.
Il problema è che devo cambiare queste due funzioni in modo da eliminare le comuni GetDecimalValueSA e GetStringValueSA e
metterle nel gateway , e far si che le funzioni(scusate la ripetizione) ritornino semplicemente dati grezzi(nel mio caso
SAFEARRAY che altro non sono che array)
quindi diventa
1)leggo il SAFEARRAY nel gateway dalla clase api:
SAFEARRAY pSACoordSysGravGateway = CSapDataLoadIteratorApi.getCoordSysGrav()
2)uso le funzioni comuni messe nel gateway e l'array letto e ritornato dalla classe dell'api:
loadDataTemp->strCoordSys = GetStringValueSAGateway(pSACoordSysGravGateway,m_n Index);
e la logica la imlemento nella classe che contiene il gateway giusto?
Il problema è che ho due classi che vanno a leggere dall' api :
CSapDataLoadIteratorApi e CSapDataStressIteratorApi che usano ambedue le stesse funzioni comuni dell' api , ma hanno un interfaccia
diversa , come posso fare?
devo creare due gateway?
se si' non ha senso!
rimane la possibilità di creare una classe comune partendo dalle due interfacce .