Whenever
there is a design that needs to be done for any new project requirement or an
enhancement, people always throw up some patterns to be implemented, the first
pattern comes out of their mouth is always Adapter, I used to think the pattern
seems to be very complex, because everybody use it as a jargon, but the irony
is, it is the simplest pattern next to Façade pattern.
Let’s test drive
Let us discuss
with a scenario. We need to create two types of report in our project by batch process
which runs at night everyday.
1.
PDF
report
2.
Doc
report.
Part of the
problem is that user favorite type of report is saved in the database and
developer will not have any control of the report type. Report that needs to be generated is known at run-time based on user choice. We need to adapt two types of report into one
type, so we can use it across the layer irrespective of the report type.
In this scenario, PDF Report will be created
by the open source code which you have control to develop and change the code, change the
functionality and development is done by the development team of the
company.
For Doc report, We use Microsoft office Interop DLL to create
the doc report, where you do not have any control over the code. You just have
to call the wordDoc.SaveAs (filename). Microsoft dll and PdfReport DLL are incompatible as per our current scenario.
Before
solving the problem with Adapter pattern, we need to understand the common
terms that are used in the Adapter Pattern world.
Target: defines the domain-specific interface
that Client uses. In our case IReportTarget
is our
Target. Client has defined
an interface for creating report.
Adapter: adapts the interface Adaptee to the Target interface. In
our case it is DocReportAdapter
which takes
care adapting the Microsoft Office Interop dll to IReportTarget
Adaptee: defines
an existing interface that needs adapting. In our case it is the Microsoft Office Interop dll which needs to adapted.
Client: One that
consumes the Target.
Below is the
code for PdfReport. This is implemented to the type IReportTarget. This is our Target
class. Here we have defined an interface which creates the
report and PdfReport implements IReportTarget
namespace AdapterPattern
{
public interface IReportTarget
{
void
CreateReport();
}
}
namespace AdapterPattern
{
public class PdfReport:IReportTarget
{
public
void CreateReport()
{
//Own
Internal Implementation for creating PDF report
}
}
}
|
. In the below code the argument type defines the report type based on the
value from database. If the argument value is doc then word report is created
by Microsoft dll and when the argument value is PDF then pdf report is created
using the open source code PdfReport
using Microsoft.Office.Interop.Word;
static void Main(string[]
args)
{
if
(args[0] == "Doc")
{
Document
wordDoc = new Document();
wordDoc.SaveAs(ref FileName, ref
FileFormat, ref LockComments,
ref
missing, ref AddToRecentFiles, ref missing,
ref
ReadOnlyRecommended, ref EmbedTrueTypeFonts,
ref
SaveNativePictureFormat, ref SaveFormsData,
ref
SaveAsAOCELetter, ref missing, ref InsertLineBreaks,
ref
AllowSubstitutions, ref LineEnding, ref AddBiDiMarks);
}
else
if (args[0] == "Pdf")
{
IReportTarget
pdfReport = new PdfReport();
pdfReport.CreateReport();
}
else
{
throw
new Exception("Invalid Report Type");
}
}
|
Let us look into the adaptee which needs to be adapted, the Microsoft office DLL we use to create the doc report needs to be adapted so it will be compatible with the report application. Since the Adaptee is not compatible we now have the redundant code
The above code
exists because the Microsoft.Office.Interop.Word,
is not compatible with IReportTarget.
Let’s make the document of Microsoft.Office.Interop.Word compatible with
adaptee, so we can use to be compatible with all reports.
using Microsoft.Office.Interop.Word;
namespace AdapterPattern
{
public class DocReportAdapter
: IReportTarget
{
public
DocReportAdapter()
{
}
public void CreateReport()
{
Document
wordDoc = new Document();
object
FileName = "myfile.doc";
if
(wordDoc.SaveFormat == (int)WdSaveFormat.wdFormatDocument)
{
wordDoc.SaveAs(ref FileName, ref
FileFormat, ref LockComments,
ref
missing, ref AddToRecentFiles, ref missing,
ref
ReadOnlyRecommended, ref EmbedTrueTypeFonts,
ref
SaveNativePictureFormat, ref SaveFormsData,
ref
SaveAsAOCELetter,ref missing, ref InsertLineBreaks,
ref
AllowSubstitutions, ref LineEnding, ref AddBiDiMarks);
}
}
}
}
|
We now create a class file which incorporates all the implementation details for the microsoft DLL and exposes only the CreateReport method which inturn has implemented IReportTarget. DocReportAdapter is created which has all the implementation details and exposes only CreateReport()
Now the Microsoft.Office.Interop.Word.Document is compatible
with our IReportTarget. So we get DocReportAdapter as Adapter
static void Main(string[] args)
{
IReportTarget
favoriteReport = null;
if
(args[0] == "Doc")
{
favoriteReport = new DocReportAdapter();
favoriteReport.CreateReport();
}
else
if (args[0] == "Pdf")
{
favoriteReport = new PdfReport();
favoriteReport.CreateReport();
}
else
{
throw
new Exception("Invalid Report Type");
}
}
|
We can use the DocReportAdapter to be used in our client Program.cs with IReportTarget, since it is compatible with our application.Now we have two report functionality implemented with IReportTarget, so we have compatible report creator
If we have another type of report that is needed in our
project, we need to just implement the functionality in a separate class file
encapsulated and then implement with IReportTarget,
so it will compatible with existing reports.
Try these examples with a class project in .Net or Java and understand all the keywords such as Adapter, Adaptee and Target. You can also define your own scenario, where it will be more easy to understand, This is the simple of all patterns, Try and let me know your comments.
Leave a comment to share what you learned, and hit the “like” button to let others know about it (make sure you’re logged into Facebook to like and comment).
Leave a comment to share what you learned, and hit the “like” button to let others know about it (make sure you’re logged into Facebook to like and comment).
No comments:
Post a Comment
Note: only a member of this blog may post a comment.