tag:blogger.com,1999:blog-72679980598141022512024-03-13T14:42:26.470+06:00Shams' BlogShamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.comBlogger14125tag:blogger.com,1999:blog-7267998059814102251.post-31492428484291146662013-05-14T03:25:00.002+06:002013-05-14T03:32:24.964+06:00Emptytons - Mimicking Static Classes in Java<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
A static class is one that has only static methods (functions) and it is meant to support procedural programming. Such classes aren't really classes in that the user of the class is only interested in the helper functions and not in creating instances of the class. While static classes are supported in C# [<a href="http://msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.80%29.aspx" target="_blank">1</a>], no such direct support exists in Java.<br />
<br />
People often mimic this feature by using a private constructor for their class:<br />
<pre> public class StaticClass1 {
// disallow instance creation by other classes
private StaticClass1() {
super();
}
public static boolean isEmpty(final String s) {
return s == null || s.isEmpty();
}
}
</pre>
But, this doesn't truly disallow creation of instances. Code (static initializers, methods, inner classes, etc.) written inside the class can still create instances of the class despite the private constructor. A dedicated Java hacker can even revert to reflection to create instances of the class.<br />
<br />
Java does however provide support for enums and that can be handily used to create these static classes or <b>Emptytons</b> who can truly avoid creation of any instances:<br />
<pre> public enum StaticClass2 {
// Empty enum trick to avoid instance creation
; // this semi-colon is important
public static boolean isEmpty(final String s) {
return s == null || s.isEmpty();
}
}
</pre>
Reflection cannot be used to create instances of such classes unlike with private constructors as reflective instantiation of enum types is prohibited [<a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9" target="_blank">2</a>, <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Constructor.html#newInstance%28java.lang.Object...%29" target="_blank">3</a>].<br />
<br />
<br />
<br />
<br />
<br />
[1] <a href="http://msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.80%29.aspx">http://msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.80%29.aspx</a><br />
[2] <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9">http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9</a><br />
[3] <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Constructor.html#newInstance%28java.lang.Object...%29">http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Constructor.html#newInstance%28java.lang.Object...%29</a></div>
Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com0tag:blogger.com,1999:blog-7267998059814102251.post-34742117447523628392011-11-14T06:45:00.002+06:002011-11-14T06:49:59.055+06:00Cleaning unversioned files from Subversion workspaceWhile git has a <a href="http://linux.die.net/man/1/git-clean">clean</a> command to remove untracked files, it seems subversion doesn't support such a command.<br /><br />I found Patric Fornasier's Blog explaining <a href="http://patforna.blogspot.com/2009/10/remove-unversioned-files-in-subversion.html">how to remove unversioned files</a> in subversion and I was very happy, but it seems theat xargs can';t handle spaces in the file names and so chokes.<br /><br />So I went ahead and created a simple script to handle whitepsace in the file names based on Patric's piping of commands.<br /><br /><br /><pre><br />#! /bin/sh<br /><br /># svn stat --no-ignore | grep ^\? | cut -b 8- | xargs rm -rfv<br /><br />FILES=`svn stat --no-ignore | grep ^\? | cut -b 9-`<br /><br />SAVEIFS=$IFS<br />IFS=$(echo "\n\b")<br /><br />for f in ${FILES}<br />do<br /> rm -rfv "${f}"<br />done<br /><br />IFS=$SAVEIFS<br /></pre>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com0tag:blogger.com,1999:blog-7267998059814102251.post-60437471037163439592008-12-19T05:51:00.029+06:002012-04-14T01:53:19.920+06:00Tri-State Checkbox using JavascriptRecently I noticed how yahoo mail select all check box only shows two<br />states while selecting/un-selecting mails to perform various actions.<br />So I decided to experiment and create a simple tri-state check box that could display my intermediate state. Below is what I ended up with:<br /><h4>Tri-State Checkbox Demo with dependent checkboxes</h4> <style type="text/css">#tristateBox img {border: 0px; margin: 0px; padding: 0px; } </style> <form onsubmit="return false; "> <span id="tristateBox" style="cursor: default;"> Select/Unselect All</span> <input id="tristateBoxInput" name="tristateBoxInput" value="0" type="hidden"> <div id="tristateBoxContainer" style="padding-left: 5px;"> <label id="label_1" for="cb_1"> <input id="cb_1" name="cb_1" value="1" type="checkbox"> Java </label><br /> <label id="label_2" for="cb_2"> <input id="cb_2" name="cb_2" value="2" checked="checked" type="checkbox"> Html </label><br /> <label id="label_3" for="cb_3"> <input id="cb_3" name="cb_3" value="3" checked="checked" type="checkbox"> Css </label><br /> <label id="label_4" for="cb_4"> <input id="cb_4" name="cb_4" value="4" checked="checked" type="checkbox"> Javascipt </label> <br /> <label id="label_5" for="cb_5"> <input id="cb_5" name="cb_5" value="5" type="checkbox"> Ruby </label> <br /><label id="label_6" for="cb_6"> <input id="cb_6" name="cb_6" value="6" type="checkbox"> Python </label> </div> </form> <script type="text/javascript">initTriStateCheckBox('tristateBox', 'tristateBoxContainer', false);</script><br />It's really simple to use. Here's what you have to do:<br /><ol><li> Include the javascript file in your html</li><li> Have a place-holder node (span in my case) to hold the image for the tri-state box</li><li> Place the related checkboxes inside a container, e.g. a div</li><li> Invoke the initTriStateCheckBox(<place holder id>, <<b>container</b> id>, <b>false</b>) function in your html</li></ol><br /><h4>Standalone Tri-State Checkbox Demo</h4> <style type="text/css">#tristateBox2 img {border: 0px; margin: 0px; padding: 0px; } </style> <form onsubmit="return false; "> <span id="tristateBox2" style="cursor: default;"> I liked this <input id="tristateBox2State" name="tristateBox2State" value="1" type="hidden"> </span><br />(Maybe/Yes/No)<br /></form> <script type="text/javascript">initTriStateCheckBox('tristateBox2', 'tristateBox2State', true);</script><br />Here's what you have to do to create a standalone one:<br /><ol><li> Include the javascript file in your html</li><li> Have a place-holder node (span in my case) to hold the image for the tri-state box</li><li> Create a hidden field to hold the state of the box </li><li> Invoke the initTriStateCheckBox(<place holder id>, <<b>hidden field</b> id>, <b>true</b>) function in your html</li></ol><br /><br />The zip file containing the javascript, images and a sample is available <a href="http://sites.google.com/site/shamsmahmood/Home/tri-state-checkbox.zip?attredirects=0">here</a>. It is also a <a href="https://github.com/mletynski/Tri-State-Checkbox">GitHub project</a> set up by Michal Letynski.Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com41tag:blogger.com,1999:blog-7267998059814102251.post-61456402582048854072008-07-13T17:51:00.028+06:002009-03-30T07:18:10.958+06:00Threaded Comments in BloggerWith all the new features being introduced in blogger, there was still a feature I would like which was not included - Threaded Comments. So I decided to mix the existing comment system with a little bit of javascript and come up with my own version of threaded comments. The advantage of using this is that you are still allowing blogger<br />to manage your comments unlike a couple of other tools I have seen. Check out the Threaded version in action<br />by adding your comments below ;).<br /><br />The idea behind this came from the simple observation that most of us use @AuthorName to reply to comments posted by other users in 'single' threaded comments. So the javascript I wrote just parses the comment bodies for this author name (or comment ids) and then searches for appropriate comments to find parents of the reply comments.<br /><br />Below is an image of how after I implemented this idea the comments section on my blog changed:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPDc_SYnqyU7wjx-_F5iva2My0kc5HsR1LQcBhmX6Ywy1fuY7bwt-o5XneKH4Srmxn9P2DI_PM_1BTbmM3Df-Og-7N7iPEyvincw9rcQLuIYPe826ee6SZR-Jdn0t-TpjZ3nP5JPrMMQdn/s1600-h/before-after-2.gif"><img id="BLOGGER_PHOTO_ID_5222469485435088386" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: pointer; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPDc_SYnqyU7wjx-_F5iva2My0kc5HsR1LQcBhmX6Ywy1fuY7bwt-o5XneKH4Srmxn9P2DI_PM_1BTbmM3Df-Og-7N7iPEyvincw9rcQLuIYPe826ee6SZR-Jdn0t-TpjZ3nP5JPrMMQdn/s400/before-after-2.gif" border="0" /></a><br /><b>Features:</b><br />In addition to the threaded support:<br /><ul style="PADDING-LEFT: 2px; MARGIN-LEFT: 2px"><li>Include multiple replies in your comment using multiple @replyTargets on separate lines in your comment </li><li>Blog authors can have their comments highlightd differently - use css styles for 'blog-author-comment' and 'blog-nonauthor-comment'</li><li>Include multiple replies in your comment using multiple @replyTargets in the comment </li><li>Hide/Show individual comments</li><li>Configurable template to display comments - use you custom template to call applyCommentTemplate(); </li></ul><br /><b>How to install:</b><br />Note: Remember to back up your existing template before making any changes to it.<br />Here are the steps to follow:<br /><ol style="PADDING-LEFT: 2px; MARGIN-LEFT: 2px"><br /><li>Include the java script file to the top of your template just before the <b:skin> tags starts<br /><div style="BORDER-RIGHT: black 1px dotted; PADDING-RIGHT: 5px; BORDER-TOP: black 1px dotted; PADDING-LEFT: 5px; FONT-SIZE: 85%; PADDING-BOTTOM: 5px; MARGIN: 10px; OVERFLOW: auto; BORDER-LEFT: black 1px dotted; WIDTH: 400px; height: 150px; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px dotted; BACKGROUND-COLOR: #ffffff"><br /><pre><script type="text/javascript"><br /> //<![CDATA[<br />/* <br /> --- Threaded Comments ---<br />v 0.9.3 15th March 2009<br />By Shams Mahmood<br />http://shamsmi.blogspot.com <br />*/<br />function Author(C,A,B){this.id=C;this.name=A;this.url=B;this.toString=function(F){var E="\t";if(F){for(var D=0;D<F;D++){E+="\t"}}return"Author[\n"+E+"id="+this.id+", \n"+E+"name="+this.name+", \n"+E+"url="+this.url+"\n"+E+"]"}}function Comment(E,H,G,C,B,D,F,A){this.id=E;this.sequenceNumber=H;this.postedTime=G;this.body=F;this.deleted=A;this.deleteUrl=B;this.deleteText=D;this.parentId="";this.children=new Array();this.level=0;this.author=C;this.getChildCount=function(){return this.children.length};this.addChild=function(I){this.children[this.getChildCount()]=I.id;I.parentId=this.id;I.level=this.level+1};this.toString=function(K){var J="\t";if(K){for(var I=0;I<K;I++){J+="\t"}}return"Comment[\n"+J+"id="+this.id+", \n"+J+"sequence="+this.sequenceNumber+", \n"+J+"deleted="+this.deleted+", \n"+J+"parentId="+this.parentId+", \n"+J+"children=["+this.children+"], \n"+J+"level="+this.level+", \n"+J+"author="+this.author.toString(1)+", \n"+J+"posted time="+this.postedTime+", \n"+J+"body="+this.body+"\n"+J+"]"}}function trimBrsFromString(C){var F=trimString(C);var B=["<br>","<br >","<br/>","<br />","<BR>","<BR >","<BR/>","<BR />"];if(F){var E=true;while(E){E=false;for(var D in B){var A=B[D];if(F.indexOf(A)==0){F=F.substring(A.length);F=trimString(F);E=true}var H=F.length;var G=F.lastIndexOf(A);if(G>=0&&G==H-A.length){F=F.substring(0,G);F=trimString(F);E=true}}}}return F}function trimString(A){var E="";if(A){var D=false;for(var B=0;B<A.length;B++){var F=A.charAt(B);if(!D&&F!=" "&&F!="\n"&&F!="\t"){D=true}if(D){E+=F}}D=false;var C=-1;for(var B=E.length-1;!D&&B>0;B--){var F=E.charAt(B);if(!D&&F!=" "&&F!="\n"&&F!="\t"){D=true;C=B}}if(C>0){E=E.substring(0,C+1)}}return E}function addItem(A,B){A[B.id]=B}function getAllItems(C){var D=new Array();var B=0;for(var A in C){D[B]=C[A];B++}return D}function getItemsCount(C){var B=0;for(var A in C){B++}return B}var ALL_AUTHORS=new Object();var ALL_COMMENTS=new Object();function getNewAuthorId(){var C=1;for(var A in ALL_AUTHORS){if(ALL_AUTHORS[A]&&ALL_AUTHORS[A].id){var B=ALL_AUTHORS[A].id;if(B>=C){C=B+1}}}return C}function createAuthor(C,A,B){return new Author(C,A,B)}function addAuthor(A){addItem(ALL_AUTHORS,A)}function getAllAuthors(){return getAllItems(ALL_AUTHORS)}function getAuthorsCount(){return getItemsCount(ALL_AUTHORS)}function findAuthor(C,B){for(var A in ALL_AUTHORS){if(ALL_AUTHORS[A]){if(ALL_AUTHORS[A].name==C&&ALL_AUTHORS[A].url==B){return ALL_AUTHORS[A]}}}return null}function getNewCommentSequence(){var C=1;for(var A in ALL_COMMENTS){if(ALL_COMMENTS[A]&&ALL_COMMENTS[A].sequenceNumber){var B=ALL_COMMENTS[A].sequenceNumber;if(B>=C){C=B+1}}}return C}function createComment(E,H,G,C,B,D,F,A){return new Comment(E,H,G,C,B,D,F,A)}function addComment(A){addItem(ALL_COMMENTS,A)}function getAllComments(){return getAllItems(ALL_COMMENTS)}function getRootComments(){var D=new Array();var C=0;for(var A in ALL_COMMENTS){var B=ALL_COMMENTS[A];if(B&&B.level==0){D[C]=B;C++}}return D}function getCommentsCount(){return getItemsCount(ALL_COMMENTS)}function findComment(B){for(var A in ALL_COMMENTS){if(ALL_COMMENTS[A]){if(ALL_COMMENTS[A].id==B){return ALL_COMMENTS[A]}}}return null}function findLastCommentByAuthorName(C){var B=null;for(var A in ALL_COMMENTS){if(ALL_COMMENTS[A]){if(ALL_COMMENTS[A].author.name==C){B=ALL_COMMENTS[A]}}}return B}function findLastCommentByPartialAuthorName(C){var B=null;for(var A in ALL_COMMENTS){if(ALL_COMMENTS[A]){if(ALL_COMMENTS[A].author.name.toLowerCase().indexOf(C.toLowerCase())==0){B=ALL_COMMENTS[A]}}}return B}function addCommentHierarchy(D,C){if(D){C[C.length]=D;var A=D.children;for(var B in A){addCommentHierarchy(findComment(A[B]),C)}}}function getCommmentsInSortedOrder(){var D=new Array();var A=getRootComments();for(var B in A){var C=A[B];addCommentHierarchy(C,D)}return D}function ParsedResult(A,B){this.parentComment=A;this.body=B;this.toString=function(){return"[parentComment="+this.parentComment+", body="+this.body+", ]"}}function findParentCommentFromDescriptor(A){var B=findComment(A);if(B==null){B=findLastCommentByAuthorName(A)}if(B==null){B=findLastCommentByPartialAuthorName(A)}return B}function parseCommentBody(B,F){B=trimString(B);var A=B.indexOf("@");if(A==0){var H=B.indexOf("\n",0);var G=B.indexOf("<",0);var D=H;if(G>0&&(G<D||D<0)){D=G}if(D>2){var O=B.substring(1,D);O=trimString(O);var K=findParentCommentFromDescriptor(O);if(K==null){var J=O.indexOf(" ");if(J>0){var N=trimString(O.substring(0,J));K=findParentCommentFromDescriptor(N);if(K!=null){D=J+1}}}if(K!=null){var P=null;var Q=D;var C=B.indexOf("@",Q+1);if(C>Q){var M=trimString(B.substring(C));P=parseCommentBody(M,C)}if(P&&P.length>0&&P[0].parentComment!=null){var L=trimString(B.substring(D,C));var I=new ParsedResult(K,L);var E=[I].concat(P);return E}else{var L=trimString(B.substring(D));var I=new ParsedResult(K,L);return[I]}return E}}}var I=new ParsedResult(null,B);return[I]}function buildComment(C,K,H,L,G,I,M,A){var F=findAuthor(C,K);if(!F){F=createAuthor(getNewAuthorId(),C,K);addAuthor(F)}var D=parseCommentBody(A,0);for(var J in D){var E="";E=D[J].body;E=trimBrsFromString(E);var B=createComment(H+"."+J,getNewCommentSequence(),L,F,I,M,E,G);addComment(B);if(D[J].parentComment!=null){D[J].parentComment.addChild(B)}}}function substituteConstant(A,D,C){var B=A;while(B.indexOf(D)>=0){B=B.replace(D,C)}return B}function substituteConstantIfValueExists(D,A,I,C,H){var J=D;var F=J.indexOf(A);var E=J.indexOf(I);while(F>0&&E>F){var B=J.substring(F,E+I.length);var G=null;if(H&&H.length>0){G=substituteConstant(B,C,H);G=G.substring(A.length,G.length-I.length)}else{G=""}J=J.replace(B,G);F=J.indexOf(A);E=J.indexOf(I)}return J}function isBlogAuthor(B){var A=false;if(window.BLOG_AUTHORS){for(var C in BLOG_AUTHORS){if(BLOG_AUTHORS[C]==B){A=true;break}}}else{if(window.BLOG_AUTHOR){A=(BLOG_AUTHOR==B)}}return A}function applyCommentTemplateToComment(F,E){var A=F;A=substituteConstant(A,"${COMMENT.ID}",E.id);A=substituteConstant(A,"${COMMENT.TIMESTAMP}",E.postedTime);A=substituteConstant(A,"${COMMENT.AUTHOR.NAME}",E.author.name);var C=(E.level>3)?"gt3":E.level;A=substituteConstant(A,"${COMMENT.LEVEL}",C);A=substituteConstantIfValueExists(A,"${COMMENT.AUTHOR.URL.EXISTS.START}","${COMMENT.AUTHOR.URL.EXISTS.END}","${COMMENT.AUTHOR.URL}",E.author.url);A=substituteConstant(A,"${COMMENT.AUTHOR.URL}",E.author.url);A=substituteConstant(A,"${COMMENT.DELETE.URL}",E.deleteUrl);A=substituteConstant(A,"${COMMENT.DELETE.TEXT}",E.deleteText);A=substituteConstant(A,"${COMMENT.BODY}",E.body);var D=isBlogAuthor(E.author.url)?"blog-author-comment":"blog-nonauthor-comment";A=substituteConstant(A,"${BLOG.AUTHOR}",D);A=substituteConstant(A,"${BLOG.POST.COMMENT.LINK}",BLOG_POST_COMMENT_LINK);var B=(E.deleted)?"deleted-comment":"";A=substituteConstant(A,"${COMMENT.DELETED.STYLE}",B);document.writeln(A)}function applyCommentTemplate(C){var D=getCommmentsInSortedOrder();for(var A in D){var B=D[A];applyCommentTemplateToComment(C,B)}}function setElementDisplay(B,C){var A=document.getElementById(B);if(A){A.style.display=C}}function setElementsDisplay(B,C){for(var A in B){setElementDisplay(B[A],C)}}function showElements(A){setElementsDisplay(A,"block")}function hideElements(A){setElementsDisplay(A,"none")}function showElement(A){setElementDisplay(A,"block")}function hideElement(A){setElementDisplay(A,"none")}function toggleElementDisplays(C,B,D){if(C.innerHTML=="[hide]"){for(var A in B){if(D[A]=="both"||D[A]=="hide"){hideElement(B[A])}}C.innerHTML="[show]"}else{for(var A in B){if(D[A]=="both"||D[A]=="show"){showElement(B[A])}}C.innerHTML="[hide]"}};// ]]><br /></script></pre><br /><br /></div></li><li><br />Next you need add the css tyles for the comments section inside you <b:skin> section. Below is the one I am using in my blog:<br /><div style="BORDER-RIGHT: black 1px dotted; PADDING-RIGHT: 5px; BORDER-TOP: black 1px dotted; PADDING-LEFT: 5px; FONT-SIZE: 85%; PADDING-BOTTOM: 5px; MARGIN: 10px; OVERFLOW: auto; BORDER-LEFT: black 1px dotted; WIDTH: 400px; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px dotted; HEIGHT: 200px; BACKGROUND-COLOR: #ffffff"><br /><pre>.comment-segment {<br />margin-top: 10px;<br />margin-right: 10px;<br />}<br />.comment-level-0 {<br />margin-left: 10px;<br />}<br />.comment-level-1 {<br />margin-left: 25px;<br />}<br />.comment-level-2 {<br />margin-left: 40px;<br />}<br />.comment-level-3 {<br />margin-left: 55px;<br />}<br />.comment-level-gt3 {<br />margin-left: 70px;<br />}<br />.blog-author-comment {<br />background-color: #F0F0BE;<br />border: 1px solid #FFFF99;<br />}<br />.blog-nonauthor-comment {<br />background-color: #B4C8F0;<br />border: 1px solid #7296E2;<br />}<br />.deleted-comment {<br />color: gray; font-STYLE: italic<br />}<br />.delete-comment-icon {<br />background: url("http://www.blogblog.com/rounders3/icon_delete13.gif")<br />no-repeat;<br />}<br />.comment-time {<br />font-size: 80%;<br />margin: inherit;<br />padding-left: 10px;<br />padding-bottom: 10px;<br />}<br />.reply-guide {<br />background-color: #FFFFFF;<br />border: #076a93 1px dotted;<br />display: none;<br />padding-right: 10px;<br />padding-left: 10px;<br />padding-bottom: 0.75em;<br />padding-top: 5px;<br />margin-right: 10px;<br />margin-bottom: 10px;<br />}<br />.reply-guide-header {<br />color: #076a93;<br />padding-top: 10px;<br />}<br />.reply-guide-list {<br />list-style: none;<br />padding-left: 2px;<br />margin-left: 2px;<br />}<br />.reply-guide-example {<br />font-size: 85%;<br />margin-right: 5px;<br />margin-bottom: 10px;<br />float: right;<br />border: 1px dotted #076a93;<br />padding: 5 5 5 5;<br />}<br /></pre><br /><br /><br /></div></li><li><br />Lastly you need to insert the template for to render the threaded blog comments.<br />You need to find the portion in your template responsible for rendering comment. In my template it started with:<br /><div style="BORDER-RIGHT: black 1px dotted; PADDING-RIGHT: 5px; BORDER-TOP: black 1px dotted; PADDING-LEFT: 5px; FONT-SIZE: 85%; PADDING-BOTTOM: 5px; MARGIN: 10px; OVERFLOW: auto; BORDER-LEFT: black 1px dotted; WIDTH: 400px; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px dotted; BACKGROUND-COLOR: #ffffff"><br /><pre><b:includable id='comments' var='post'><br /><div class='comments' id='comments'><br />...<br /></div><br /></b:includable><br /></pre><br /></div><br />I just replaced that <b:includable> with the following:<br /><div style="BORDER-RIGHT: black 1px dotted; PADDING-RIGHT: 5px; BORDER-TOP: black 1px dotted; PADDING-LEFT: 5px; FONT-SIZE: 85%; PADDING-BOTTOM: 5px; MARGIN: 10px; OVERFLOW: auto; BORDER-LEFT: black 1px dotted; WIDTH: 400px; PADDING-TOP: 5px; BORDER-BOTTOM: black 1px dotted; HEIGHT: 200px; BACKGROUND-COLOR: #ffffff"><br /><pre><br /><b:includable id='comments' var='post'><br /> <div class='comments' id='comments'><br /> <a name='comments'/><br /> <b:if cond='data:post.allowComments'><br /> <h4><br /> <b:if cond='data:post.numComments == 1'> 1 <data:commentLabel/>:<br /> <b:else/><data:post.numComments/><data:commentLabelPlural/>: <br /> </b:if><br /> </h4><br /><br /> <b:if cond='data:post.numComments > 0'><br /> <!-- Include a post comment link before rendering the comments --><br /> <p class='comment-footer'><br /> <b:if cond='data:post.embedCommentForm'><br /> <b:include data='post' name='comment-form'/><br /> <b:else/><br /> <b:if cond='data:post.allowComments'><br /> <a expr:href='data:post.addCommentUrl' <br /> expr:onclick='data:post.addCommentOnclick'><data:postCommentMsg/></a><br /> </b:if><br /> </b:if><br /> </p><br /> </b:if><br /><br /> <!-- Loop through the comments adding the comment bodies in a hidden div --><br /> <b:loop values='data:post.comments' var='comment'><br /> <div style="display: none;" expr:id='"comment-body-" + data:comment.id' ><br /> <data:comment.body/><br /> </div><br /> </b:loop><br /> <!-- Now create the comment using our javascript --><br /> <script type="text/javascript"><br /> // USE THIS if YOU Have multiple Authors adding them in a comma separated form after removing the '//' from the next line<br /> // var BLOG_AUTHORS = ['http://www.blogger.com/profile/firstauthor', 'http://www.blogger.com/profile/secondauthor', 'http://www.blogger.com/profile/thirdauthor'];<br /> // Use this if you have just one author like this blog :)<br /> var BLOG_AUTHOR = 'http://www.blogger.com/profile/10301627897367423203';<br /> var BLOG_POST_COMMENT_LINK = '<data:post.addCommentUrl/>';<br /><br /> var eCommentDelete = false;<br /> var eAuthorUrl = '';<br /> <b:loop values='data:post.comments' var='comment'><br /> eCommentDelete = false;<br /> eAuthorUrl = '';<br /> <b:if cond='data:comment.authorUrl'><br /> eAuthorUrl = "<data:comment.authorUrl/>";<br /> </b:if><br /> <b:if cond='data:comment.isDeleted'><br /> eCommentDelete = true;<br /> </b:if><br /> <br /> buildComment("<data:comment.author/>", eAuthorUrl, <br /> "<data:comment.id/>", "<data:comment.timestamp/>", eCommentDelete, <br /> "<data:comment.deleteUrl/>", "<data:top.deleteCommentMsg/>", <br /> document.getElementById('comment-body-<data:comment.id/>').innerHTML);<br /> </b:loop><br /> // <![CDATA[<br /> var eCommentTemplate = '' +<br /> '<div class="comment-segment comment-level-${COMMENT.LEVEL} ${BLOG.AUTHOR} ${COMMENT.DELETED.STYLE}" >' + '\n' +<br /> ' <a name="comment-${COMMENT.ID}"></a>' + '\n' +<br /> ' <span style="float: right; margin-right: 5px; " >' + '\n' +<br /> ' <a href="#" ' + '\n' +<br /> ' onclick="toggleElementDisplays(this, ' +<br /> '[\'comment-${COMMENT.ID}-body\', \'comment-${COMMENT.ID}-footer\', \'reply-guide-${COMMENT.ID}\'], ' +<br /> '[\'both\', \'both\', \'hide\']); return false;" >[hide]</a>' + '\n' +<br /> ' </span>' + '\n' +<br /> ' <span class="comment-author" >' +<br /> '${COMMENT.AUTHOR.URL.EXISTS.START}' +<br /> '<a href="${COMMENT.AUTHOR.URL}" rel="nofollow">' +<br /> '${COMMENT.AUTHOR.URL.EXISTS.END}' +<br /> '${COMMENT.AUTHOR.NAME}' +<br /> '${COMMENT.AUTHOR.URL.EXISTS.START}' +<br /> '</a>' +<br /> '${COMMENT.AUTHOR.URL.EXISTS.END}</span>' + '\n' +<br /> ' said... ' + '\n' +<br /> ' <div id="comment-${COMMENT.ID}-body" class="comment-body" ><p>${COMMENT.BODY}</p></div>' + '\n' +<br /> ' <span class="comment-time">on ${COMMENT.TIMESTAMP}</span>' + '\n' +<br /> ' <div id="reply-guide-${COMMENT.ID}" class="reply-guide comment-level-0 " >' + '\n' +<br /> ' <span style="float: right;" ><a href="#" onclick="hideElement(\'reply-guide-${COMMENT.ID}\'); return false;" >[hide]</a></span>' + '\n' +<br /> ' <h4 class="reply-guide-header">How to Reply to this comment</h4>' + '\n' +<br /> ' <span>' + '\n' +<br /> ' To reply to this comment please ensure that <b>one</b> of the following lines: ' + '\n' +<br /> ' <ul class="reply-guide-list">' + '\n' +<br /> '<li>@${COMMENT.ID}</li>' + '\n' +<br /> '<li>@${COMMENT.AUTHOR.NAME}</li>' + '\n' +<br /> ' </ul>' + '\n' +<br /> ' is the <b>first line</b> of your comment. ' + '\n' +<br /> ' <br />' + '\n' +<br /> ' <a href="${BLOG.POST.COMMENT.LINK}"' + '\n' +<br /> ' >Click here to enter your reply</a>' + '\n' +<br /> ' </span>' + '\n' +<br /> ' </div>' + '\n' +<br /> ' <div id="comment-${COMMENT.ID}-footer" class="comment-footer">' + '\n' +<br /> ' <span><a ' +<br /> 'href="#" onclick="showElement(\'reply-guide-${COMMENT.ID}\'); return false;" >Reply</a></span> ' + '\n' +<br /> ' <span><a href="#comment-${COMMENT.ID}">Permalink</a></span> ' + '\n' +<br /> ' <span><a href="${COMMENT.DELETE.URL}" title="${COMMENT.DELETE.TEXT}" style="text-decoration: none;" ><span class="delete-comment-icon"> </span></a></span>' + '\n' +<br /> ' </div>' + '\n' +<br /> '</div>' + '\n';<br /> <br /> applyCommentTemplate(eCommentTemplate);<br /> // ]]><br /> </script><br /> <p class='comment-footer'><br /> <a expr:href='data:post.addCommentUrl' expr:onclick='data:post.addCommentOnclick'><data:postCommentMsg/></a><br /> </p><br /> </b:if><br /> <div id='backlinks-container'><br /> <div expr:id='data:widget.instanceId + "_backlinks-container"'><br /> <b:if cond='data:post.showBacklinks'><br /> <b:include data='post' name='backlinks'/><br /> </b:if><br /> </div><br /> </div><br /> </div><br /></b:includable><br /></pre><br /></div></li></ol><br /><br /><b>Remember</b> to replace the <br /><pre>var BLOG_AUTHORS = <br /> ['http://www.blogger.com/profile/firstauthor', <br /> 'http://www.blogger.com/profile/otherauthor'];</pre> OR <br /><pre>var BLOG_AUTHOR = 'http://www.blogger.com/profile/onlyauthor';</pre> segment with <b>your appropriate profile url(s).</b><br /><br />A <a href="http://sites.google.com/site/shamsmahmood/Home/template-20090315-1210.xml.txt?attredirects=0">sample blogger template</a> is also available in case you want to skip some of the work.<br /><br /><b>Future work:</b><br />Unfortunately the way blogger comments need to be posted it is the responsibilty of the user now to include a @replyTarget line to the top of her comment. Once blogger supports inline comment forms completely (currently it is available only in draft mode) it will be possible to relieve the user of this task and use javascript to auto insert the @replyTarget line into the form.<br /><br />Feel free to use this in your blogs and let me know your thoughts/bugs you find while using this :)<br /><br />Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com257tag:blogger.com,1999:blog-7267998059814102251.post-85523729513746932442008-05-04T18:45:00.023+06:002008-07-06T15:46:22.227+06:00Implementation of My Java7 Wishlist<p style="MARGIN-BOTTOM: 0in">Last month I blogged about <a href="http://shamsmi.blogspot.com/2008/04/my-java7-wishlist-regarding-collections.html">my java7 wishlist regarding collections</a>. There I was redirected to a similar post by <a href="http://jroller.com/scolebourne/entry/java_7_list_and_map">Stephen Colebourne</a> and also introduced to an open source project <a href="https://kijaro.dev.java.net/">kijaro</a> where others had implemented their wishlists and I could try out mine.<br /></p><p style="MARGIN-BOTTOM: 0in">After three weekends I am now pleased to announce that I have implemented my wishlist. My implementation at <a href="https://kijaro.dev.java.net/svn/kijaro/branches/concisecollections/">a branch of kijaro</a> contains a merger of my wishlist and those mentioned by Stephen in his blog. Features implemented are:</p><ul><li><p style="MARGIN-BOTTOM: 0in">Array Index access syntax for Lists and Maps<br /><span style="font-family:Courier New, monospace;"><span style="font-size:85%;">myList[0]</span></span> instead of <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">myList.get(0)</span></span> and<br /><span style="font-family:Courier New, monospace;"><span style="font-size:85%;">myMap[“key”]</span></span> instead of <span style="font-family:Courier New, monospace;"><span style="font-size:85%;">myMap.get(“key”</span></span><span style="font-family:Courier New, monospace;">)</span><br /></p></li></ul><ul><li><p style="MARGIN-BOTTOM: 0in">Concise syntax to initialize and fill Collections<br /><span style="font-family:Courier New, monospace;"><span style="font-size:85%;">new HashMap<Integer, String>(5) [1: “one”, 2:”two”, 3:”three”, ]</span></span><br />instead of<br /><span style="font-family:Courier New, monospace;"><span style="font-size:85%;">HashMap<Integer, String> m1 = new HashMap<Integer, String>(5);<br /></span></span><span style="font-size:85%;"><span style="font-family:Courier New, monospace;">m1.put(1, “one”);<br /></span></span><span style="font-size:85%;"><span style="font-family:Courier New, monospace;">m1.put(2, “two”);<br /></span></span><span style="font-size:85%;"><span style="font-family:Courier New, monospace;">m1.put(3, “three”);</span></span></p></li></ul><p style="MARGIN-BOTTOM: 0in"><span style="color:#000000;">There was a catch while implementing the second feature as the expression needed to be converted to another expression and not a series of statements. Hence I needed to make use of a utility method to execute the set of statements to populate a Collection or a Map.</span></p><br /><span style="color:#000000;">It was really exciting for me to see a .java file with the above syntax compiled into a .class file. Below is an example of such a file and the corresponding jdk4 compliant code it was converted to during the compilation process.</span><br /><pre><br />public class TestConcise {<br /> public static void main(String[] args) {<br /> boolean b = new java.util.LinkedList<String>()<br /> ["a", "b", "c" ].add("d");<br /> param(new java.util.ArrayList<String>() {<br /> public boolean add(String e) {<br /> return super.add(e);<br /> }<br /> } ["a", "b", "c" ]<br /> );<br /> java.util.Map<Integer, String> m1 = ret();<br /> m1[2] = "two";<br /> <b><br /> java.util.LinkedList<String> l1 = new<br /> java.util.LinkedList<String>()["a", "b", "c" ];<br /> m1[3] = l1[2];<br /> l1[0] = m1[0];<br /> l1[1] = "one";<br /> </b><br /> }<br /><br /> private static void param(<br /> final java.util.Collection<? extends Object> coll){<br /> System.out.println(coll);<br /> }<br /><br /> private static java.util.Map<Integer, String> ret() {<br /> return new java.util.HashMap<Integer, String>() {} <br /> [1:"a", 2:"b", ];<br /> }<br />}<br /></pre><br /><p style="MARGIN-BOTTOM: 0in">was converted to</p><br /><pre><br />class TestConcise$1 extends java.util.ArrayList {<br /> TestConcise$1() {<br /> super();<br /> }<br /><br /> public boolean add(String e) {<br /> return super.add(e);<br /> }<br /><br /> /*synthetic*/ public boolean add(Object x0) {<br /> return this.add((String)x0);<br /> }<br />},<br /><br />class TestConcise$2 extends java.util.HashMap {<br /> TestConcise$2() {<br /> super();<br /> }<br />},<br /><br />public class TestConcise {<br /> public TestConcise() {<br /> super();<br /> }<br /><br /> public static void main(String[] args) {<br /> boolean b = java.util.CollectionUtil.fillCollection(<br /> new java.util.LinkedList(), <br /> new String[]{"a", "b", "c"}).add("d");<br /> param(java.util.CollectionUtil.fillCollection(<br /> new TestConcise$1(), new String[]{"a", "b", "c"}));<br /> java.util.Map m1 = ret();<br /> m1.put(Integer.valueOf(2), "two");<br /> <b><br /> java.util.LinkedList l1 = <br /> java.util.CollectionUtil.fillCollection( <br /> new java.util.LinkedList(), <br /> new String[]{"a", "b", "c"});<br /> m1.put(Integer.valueOf(3), l1.get(2));<br /> l1.set(0, m1.get(Integer.valueOf(0)));<br /> l1.set(1, "one");<br /> </b><br /> }<br /><br /> private static void param(<br /> final java.util.Collection coll) {<br /> System.out.println(coll);<br /> }<br /><br /> private static java.util.Map ret() {<br /> return java.util.CollectionUtil.fillMap(<br /> new TestConcise$2(),<br /> new Integer[]{Integer.valueOf(1), Integer.valueOf(2)},<br /> new String[]{"a", "b"});<br /> }<br />}<br /></pre>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com113tag:blogger.com,1999:blog-7267998059814102251.post-50458063740027338182008-04-05T18:56:00.022+06:002008-07-14T01:06:18.305+06:00My Java7 Wishlist regarding Collections<b>Update:</b> I've implemented the features mentioned below. Read more about it at another post: <a href="http://shamsmi.blogspot.com/2008/05/implementation-of-my-java7-wishlist.html" >Implementation of My Java7 Wishlist</a><br /><br />There are tons of <a href="http://java7.tumblr.com/">feature requests for java7</a>. Most of the them center around <a href="http://gafter.blogspot.com/">closures</a>, super-packages, extension methods, <a href="http://blog.jeremymartin.name/2008/03/my-java-7-wishlist.html">tuples</a>, etc which are all new concepts for the language. I have been wondering why no one has bothered with improving support for some of the existing concepts/classes – in particular the syntax regarding Collection classes.<br /><br />Collections have been a hot topic, although indirectly, with the introduction of generics in java 5. These classes are used more and more often in daily development – at least by me J and all my colleagues. So I am considering proposing giving the Collections citizens of java additional privileges like Arrays have receive right from the start. My wish list features mainly around syntactic enhancements to improve readability and make the code more concise (<a href="http://robbyoconnor.blogspot.com/2008/03/concise-instance-creation-expressions.html">inspired by Rob’s CICE</a>).<br /><br />My first proposal revolves around making the collection instantiation syntax.<br />For a Collection class we might consider something similar to arrays:<br /><br />Instead of:<br /><br /><span style="font-family:courier new;"><blockquote><span style="font-family:courier new;font-size:100%;color:#000000;">Collection<String> c = new ArrayList<string>();<br />c.add(“one”);<br />c.add(“two”);<br />c.add(“three”);</span></blockquote><br /></span>Use:<br /><br /></span><span style="font-family:courier new;"><blockquote><span style="font-family:courier new;font-size:100%;"><span style="color:#000000;">Collection<String> c = new ArrayList {“one”, “two”, “three” };</span><br /></span></blockquote></span><br />For a Map instance we might consider the javascript like syntax:<br /><br />Instead of:<br /><br /><span style="font-family:courier new;"><blockquote><span style="font-family:courier new;color:#000000;">Map<String, Integer> m = new HashMap<string,>();<br />m.put(“one”, 1);<br />m.put(“two”, 2);<br />m.put(“three”, 3);</span></blockquote><br /></span>Use:<br /><br /></span><span style="font-family:courier new;"><blockquote><span style="font-family:courier new;color:#000000;">Map<String, Integer> m = new HashMap { “one”:1, “two”:2, “three”:3 };</span></blockquote></span><br />However it becomes tricky when we wish to invoke a particular conctructor of the actual implementing class. I am yet to come up with a pretty format for that one but something like<br /><br /></span><span style="font-family:courier new;"><blockquote><span style="font-family:courier new;color:#000000;">Collection<String> c = new ( ArrayList(3) ) { “one”, “two”, “three” };<br />Map<String, Integer> m = new ( HashMap(5, 0.8) ) { “one”:1, “two”:2, “three”:3 };</span></blockquote><br /></span>should work fine.<br /></span><br />My second proposal is to allow syntax to treat Maps like Arrays. After all Maps are Associative Arrays J.<br />So one should be able to write<br /><br /><span style="font-family:courier new;"><blockquote><span style="font-family:courier new;color:#000000;">m[“four”] = 4;<br />int i = m[“two”] ;</span></blockquote><br /></span>instead of<br /><br /></span><span style="font-family:courier new;"><blockquote><span style="font-family:courier new;color:#000000;">m.put(“four”, 4);<br />int i = m.get(“two”);</span></blockquote></span><br /><br />These help make the code compact and more readable.<br /><br />I would be glad if you shared with me what you think of this proposal or if you have any similar ideas.<br /><br /><b>Update:</b> I've implemented the features mentioned above. Read more about it at another post: <a href="http://shamsmi.blogspot.com/2008/05/implementation-of-my-java7-wishlist.html" >Implementation of My Java7 Wishlist</a>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com33tag:blogger.com,1999:blog-7267998059814102251.post-25207906856332568662008-03-06T12:40:00.029+06:002008-07-06T15:47:31.317+06:00Internationalize Swing's JFileChooser in Unicode (Bangla)Recently I had to develop a small demo application for one of the leading newspapers in Bangladesh. I decided to localize my application and see all messages in Bangla. Searching Google I came across this article “<a href="http://beradrian.wordpress.com/2007/07/30/internationalization-for-swing-standard-components/">Internationalization for Swing standard components</a>”. This set me off in the right direction. However, there were some little tweaks I had to perform to get Bangla working. Firstly I had to set the font for the components user in JFileChooser.<br /><br /><span style="font-family:lucida grande;"><span style="color:#3333ff;"><span style="font-size:85%;color:#666666;">final Font FONT_SOLAIMAN_LIPI = new Font("SolaimanLipi", Font.PLAIN, 15);<br />final FontUIResource eFontUIResource = new FontUIResource(FONT_SOLAIMAN_LIPI);<br />UIManager.put("Button.font", eFontUIResource);<br />UIManager.put("ToolTip.font", eFontUIResource);<br />UIManager.put("Label.font", eFontUIResource);<br />UIManager.put("EditorPane.font", eFontUIResource);<br />UIManager.put("TableHeader.font", eFontUIResource);</span><br /></span></span><br />Next I had to set message values for properties as mentioned in Adrian's blog. However I had to set a couple of extra properties also<br /><br /><span style="font-family:lucida grande;font-size:85%;color:#3333ff;"><span style="color:#666666;">UIManager.put("FileChooser.directoryOpenButtonText");<br />UIManager.put("FileChooser.directoryOpenButtonToolTipText");</span><br /></span><br />Finally there was this trouble of changing the tooltip for the home directory. The default JFileChooser implementation sets the tooltip to the name of the home directory which in my case (as will be in most cases :) ) was in english. So I had to end up writing a small visitor that would find the home folder button and reset the tooltip of the button as follows:<br /><br /><span style="font-family:lucida grande;font-size:85%;color:#3333ff;"><span style="color:#666666;">final String eHomeFolderName = eFileChooser.getFileSystemView().getHomeDirectory().getName();<br />MySwingComponentVisitor eVisitor = new MySwingComponentVisitor(eFileChooser, JButton.class) {<br />@Override<br />public boolean onComponentVisited(JComponent pVisitedComponent) {<br />JButton eButtonComponent = (JButton) pVisitedComponent;<br />if (eHomeFolderName.equals(eButtonComponent.getToolTipText())) {<br />eButtonComponent.setToolTipText(<br />getLocalizedMessage("homeFolderToolTipText"));<br />return STOP_VISITING;<br />}<br />return CONTINUE_VISITING;<br />}<br />};<br />eVisitor.visitComponents();</span><br /></span><br />And the results were just so pleasing. A JFileChooser almost entirely in Bangla. Below are images showing how the JFileChooser transformed :)<br /><br /><br /><a href="http://lh6.google.com/shams.mahmood/R8-WXpM8ORI/AAAAAAAACfw/DJnlhyUCZe8/file-chooser-english-to-bangla-1.png"><img style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 400px; CURSOR: hand" alt="Click to enlarge" src="http://lh6.google.com/shams.mahmood/R8-WXpM8ORI/AAAAAAAACfw/DJnlhyUCZe8/file-chooser-english-to-bangla-1.png" border="0" /></a><br /><a href="http://lh3.google.com/shams.mahmood/R8-WX5M8OSI/AAAAAAAACf4/gAkjpVjh0e4/file-chooser-english-to-bangla-2.png"><img style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 400px; CURSOR: hand" alt="Click to enlarge" src="http://lh3.google.com/shams.mahmood/R8-WX5M8OSI/AAAAAAAACf4/gAkjpVjh0e4/file-chooser-english-to-bangla-2.png" border="0" /></a>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com5tag:blogger.com,1999:blog-7267998059814102251.post-30305684397343632792008-02-27T21:14:00.006+06:002008-08-21T02:46:47.626+06:00Shell script to find last created file in a directoryI'm quite new to shell scripting and with my introduction to pipes and the beginners ls and tail commands I was able to come up with quite a simple shell script to find the last modified file in a directory.<br /><br />The idea is very simple, its built on top of three facts :<br />1) ls -t -r command which sorts the file in a directory by creation date in reverse order,<br />2) tail -n 1 command which outputs the last line of the input passed to it, and<br />3) '' , the pipe which redirects the output of one process to the input of another.<br /><br />So finally I came up with this simple script :)<br /><pre>ls -t -r | tail -n 1</pre>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com7tag:blogger.com,1999:blog-7267998059814102251.post-75153018914453648642007-08-26T21:32:00.000+06:002007-10-06T19:46:34.516+06:00Cool way to create new Class in EclipseRecently I was amazed in how I could create a new class inside eclipse. All I needed to do was copy the source code for a class and paste, using Ctrl + V, into a selected package in eclipse. It automatically created a new java class and added the code to the file. I tired this same technique with another ide but failed to see the support there. I think this is a really cool feature provided by eclipse.Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com3tag:blogger.com,1999:blog-7267998059814102251.post-7475031557933013322007-08-26T20:33:00.001+06:002008-03-09T22:19:07.830+06:00Maven Plugin to generate code using Eclipse JDTRecently we were facing troubles with the generated sources for our project. The problem was that the java sources generated for our web service client using <a href="http://incubator.apache.org/cxf/">cxf</a> did not have a proper toString() or equals() method both of which we needed.<br /><br />We were using <a href="http://maven.apache.org/">maven</a> for building our project and manage dependencies. The idea struck me why not have a maven plugin to modify the generated sources. So we decided on creating a maven plugin to do just that. I had previous experience with eclipse and knew it had something called <a href="http://www.eclipse.org/jdt/">JDT</a> to form a syntax tree from java source text. In addition, <a href="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html">maven build life cycle</a> has a process-sources phase just after the generate-sources phase which was just perfect for us.<br /><br />Now we have to plugin which generates the toString(), equals() and hashCode() methods and relieved us a lot of debugging effort.<br /><br />Below is sample code generated using the plugin on a class:<br /><br /><span style="color: rgb(51, 51, 153);"><blockquote><span style="color: rgb(51, 51, 153);">@Override public boolean equals( final Object pOtherObject){<br />if (pOtherObject == null) {<br />return false;<br />}<br />if<br />(this.getClass().equals(pOtherObject.getClass())) {<br />return id ==<br />((Event)pOtherObject).id;<br />}<br />return super.equals(pOtherObject);<br />}<br /><br />@Override public int hashCode(){<br />return this.getId();<br />}<br /><br />@Override public String toString(){<br />StringBuilder eStringBuilder;<br />eStringBuilder=new StringBuilder();<br />eStringBuilder.append("Class");<br />eStringBuilder.append(" : ");<br />eStringBuilder.append(getClass());<br />eStringBuilder.append(" , ");<br />eStringBuilder.append("Id");<br />eStringBuilder.append(" : ");<br />eStringBuilder.append(id);<br />eStringBuilder.append(" , ");<br />eStringBuilder.append("Artists");<br />eStringBuilder.append(" : ");<br />if (artists != null) {<br />eStringBuilder.append(" [ ");<br />for ( Artist eArtist : artists) {<br />if<br />(eArtist != null) {<br />eStringBuilder.append(eArtist);<br />} else {<br />eStringBuilder.append("null");<br />}<br />eStringBuilder.append(" , ");<br />}<br />eStringBuilder.append(" ] ");<br />} else {<br />eStringBuilder.append("null");<br />}<br />eStringBuilder.append(" , ");<br />eStringBuilder.append("Name");<br />eStringBuilder.append(" : ");<br />eStringBuilder.append(name);<br />eStringBuilder.append(" , ");<br />return<br />eStringBuilder.toString();<br />}</span></blockquote></span><br /><span style="color: rgb(51, 51, 153);"></span><br /><span style="color: rgb(51, 51, 153);"></span>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com6tag:blogger.com,1999:blog-7267998059814102251.post-30463792457253534382007-08-12T21:37:00.000+06:002007-08-12T21:56:49.590+06:00Abstract Factory Pattern<p><span style="font-family:Tahoma;font-size:85%;">Consider now that the <a href="http://shamsmi.blogspot.com/2007/08/factory-method-pattern.html">Client changes her requirements further</a>. (These clients are really clever bunch of people. They keep changing their requirements again and again and expect us engineers to meet the deadlines. Fortunately we have design patterns to come to our rescue). The client now wants to have specific glasses and straws for the drinks from the different fountains.</span></p><p><span style="font-family:Tahoma;font-size:85%;">We are already aware of two previous design pattern suggestions:</span><br /></p><p><span style="font-family:Tahoma;"><blockquote><p><b>"<i>Encapsulate what varies</i>"</b></span><span style="font-family:Tahoma;"><br /></p></blockquote><p></p></span><span style="font-family:Tahoma;"><blockquote><p><b>"<i>Depend on Abstractions, not on Concretions</i>"</b></p></blockquote></span><p><span style="font-family:Tahoma;font-size:85%;">Its time to familiarize ourselves with yet another one:</span></p><span style="font-family:Tahoma;"><blockquote><p><b>"<i>Favor Object composition over inheritance</i>"</b></span><br /></p></blockquote><p><span style="font-family:Tahoma;font-size:85%;">We will be using this set of suggestions to solve our problem.</span></p><p><span style="font-family:Tahoma;font-size:85%;">Firstly we realize that we will need three methods inside our </span><span style="font-family:Lucida Console;font-size:85%;">Factory</span><span style="font-family:Tahoma;font-size:85%;"> now. Previously there was only </span><span style="font-family:Lucida Console;font-size:85%;">createDrink()</span><span style="font-family:Tahoma;font-size:85%;"> but now we need </span><span style="font-family:Lucida Console;font-size:85%;">createGlass()</span><span style="font-family:Tahoma;font-size:85%;"> and </span><span style="font-family:Lucida Console;font-size:85%;">createStraw()</span><span style="font-family:Tahoma;font-size:85%;">. Both our Factories will have these methods so it would be a nice idea to abstract our Factories. As a result we will no longer keep our methods static in<br />the FountainFactories.</span><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdd9FZIppiLxWMPSyOyay_rHgH3Lii0ZE9wyc75RR369Jly2Hd6Y9LkN5oI7FFMP66O9Z04n37u3ddOopYrXtsKS-Asv6S1UrxgHD0C_kz3p0I6kpfqzPmzwD8X3OQycfMkEx-BlPCqr-6/s1600-h/Drink+Images+1.gif"><img id="BLOGGER_PHOTO_ID_5097839292095074914" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgdd9FZIppiLxWMPSyOyay_rHgH3Lii0ZE9wyc75RR369Jly2Hd6Y9LkN5oI7FFMP66O9Z04n37u3ddOopYrXtsKS-Asv6S1UrxgHD0C_kz3p0I6kpfqzPmzwD8X3OQycfMkEx-BlPCqr-6/s320/Drink+Images+1.gif" border="0" /></a><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN6LmcXsrMSu7cfU8gkbPhN_hNqmQQXFXd4g3bZKYFp0faH9WR08Tu78Q6a69IOcMPsx05a7shBsUFkzeNYf3XnhH1CLMhfjPrkYFifI4rs-LiHzAXOURZqGm0aS0Bpjg7cM0bMeRpMFvY/s1600-h/Drink+Images+2.gif"><img id="BLOGGER_PHOTO_ID_5097839292095074930" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhN6LmcXsrMSu7cfU8gkbPhN_hNqmQQXFXd4g3bZKYFp0faH9WR08Tu78Q6a69IOcMPsx05a7shBsUFkzeNYf3XnhH1CLMhfjPrkYFifI4rs-LiHzAXOURZqGm0aS0Bpjg7cM0bMeRpMFvY/s320/Drink+Images+2.gif" border="0" /></a><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc18ATbbC4idwoaRmPnfRgVQP9bxXFeALDX44Je5xB0yZxnVQKzmJwgcx1WgIICpNPhDJfe-kVlVr7oHwnaWefveeyazxVGNHFxuPW-bmXEaNrzmuoszT-U6FXfYoe_gkyrwIkO8RHRK8P/s1600-h/Drink+Images+3.gif"><img id="BLOGGER_PHOTO_ID_5097839292095074946" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc18ATbbC4idwoaRmPnfRgVQP9bxXFeALDX44Je5xB0yZxnVQKzmJwgcx1WgIICpNPhDJfe-kVlVr7oHwnaWefveeyazxVGNHFxuPW-bmXEaNrzmuoszT-U6FXfYoe_gkyrwIkO8RHRK8P/s320/Drink+Images+3.gif" border="0" /></a><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBOcbjJuPGACPro4O5tWGrJ7-nFVQwcx9ku4rL650hhJErSJn-wZ20adljxMnwEbxWFGnNf8Px-csgNtGhvWAV38iNdgQAS1ZQKerNRf9E5l5LvoOZSoajYWEARNzb0WdxutJ38RnqID5C/s1600-h/abstract_factory_1.gif"><img id="BLOGGER_PHOTO_ID_5097839296390042258" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBOcbjJuPGACPro4O5tWGrJ7-nFVQwcx9ku4rL650hhJErSJn-wZ20adljxMnwEbxWFGnNf8Px-csgNtGhvWAV38iNdgQAS1ZQKerNRf9E5l5LvoOZSoajYWEARNzb0WdxutJ38RnqID5C/s320/abstract_factory_1.gif" border="0" /></a> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi8ZgMf-4eddHOFEf3viowhdqunk1IWoRbd5dkkmdfHXwnfpBVAgJweFfRhbfrxjYLq4g1wwNCiKrzCUyHJSOwcXc1Ey3_lDve9xXxkVSQHKg939M3FWHpCgLA41VwuMPv4BXU-ufz7TUG/s1600-h/abstract_factory_2.gif"><img id="BLOGGER_PHOTO_ID_5097839296390042274" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi8ZgMf-4eddHOFEf3viowhdqunk1IWoRbd5dkkmdfHXwnfpBVAgJweFfRhbfrxjYLq4g1wwNCiKrzCUyHJSOwcXc1Ey3_lDve9xXxkVSQHKg939M3FWHpCgLA41VwuMPv4BXU-ufz7TUG/s320/abstract_factory_2.gif" border="0" /></a> <span style="font-family:Tahoma;font-size:85%;">Notice that the methods inside the Factory are actually Factory Methods. </span></p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidENBz3E-DdD2Dofe4f3wgbipMMxw5xVSmeV0-pUDQ0IBxTKCBSgq2M7PgV39MWvS0GJmmU8dQxB8CMxLO6299sC6B6vAhnJ3ILgnFPsTDrbNes9VKmJA2QkCDietcYhrJGF0kwxwedT5L/s1600-h/abstract_factory_3.gif"><img id="BLOGGER_PHOTO_ID_5097839652872327858" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidENBz3E-DdD2Dofe4f3wgbipMMxw5xVSmeV0-pUDQ0IBxTKCBSgq2M7PgV39MWvS0GJmmU8dQxB8CMxLO6299sC6B6vAhnJ3ILgnFPsTDrbNes9VKmJA2QkCDietcYhrJGF0kwxwedT5L/s320/abstract_factory_3.gif" border="0" /></a> <span style="font-family:Tahoma;font-size:85%;">Implementing the Fountain is now a simple issue. All we need is to compose the FountainFactory inside the Fountain and our problem will be solved. Since we have managed to abstract our Factory we are using what is known as the Asbtract Factory design pattern. Our fountain class is now completely oblivious of the Drinks, Glasses and Straws being created. Our factories have grouped together the products that need to be created which we can consider as a family, e.g. Pepsi Drinks, Pepsi Glass and Pepsi Straw. The Factory also ensures that there is consistency amongst objects. In our current implementation it will be almost impossible to generate a Cocacola with a Pepsi<br />Glass. </span><br /><br /><p><span style="font-family:Tahoma;font-size:85%;">Formally we may define the Abstract Factory as follows:<br /></p></span><span style="font-family:Tahoma;font-size:85%;"><blockquote><p>The Abstract Factory pattern is one level of abstraction higher than the ‘factory pattern’. You can use this pattern when you want to return one of several related classes of objects, each of which can return several different objects on request. In other words, the Abstract Factory is a factory object that returns one of several factories. </span></p></blockquote><p><span style="font-family:Tahoma;font-size:85%;">There are other mechanisms of using the </span><span style="font-family:Lucida Console;font-size:85%;">AbstractFactory</span><span style="font-family:Tahoma;font-size:85%;"> inside the </span><span style="font-family:Lucida Console;font-size:85%;">Fountain</span><span style="font-family:Tahoma;font-size:85%;"> class. I'll leave that discussion for a later time.</span></p><p><span style="font-family:Tahoma;font-size:85%;">With all the advantages including abstraction and localization of information provided by the Abstract Factory pattern it is easy to get carried away. One should be careful in choosing this pattern over the Simple Factory or Factory Method pattern. For one extending the abstract factory is not easy because the AbstractFactory abstraction fixes the set of products that can be created. So adding new products, for example </span><span style="font-family:Lucida Console;font-size:85%;">Topping</span><span style="font-family:Tahoma;font-size:85%;">s on </span><span style="font-family:Lucida Console;font-size:85%;">Drink</span><span style="font-family:Tahoma;font-size:85%;">s, requires adding methods in the abstract factory which involves changing the AbstractFactory class and all its subclasses. Secondly, if the client needs to know of the subclasses, for example the actual drinks created, explicit down casting is required of drinks created from the concrete factories. Thirdly it is very difficult to add a new type of family of products in the abstract factory as the child class then needs to implement all the methods defined in the abstract class. For example if we wish to add a third type of fountain for RC-Cola and the RC-Cola does not have its own Straw it will be impossible to fit this </span><span style="font-family:Lucida Console;font-size:85%;">RCColaFountainFactory</span><span style="font-family:Tahoma;font-size:85%;"> as a child of the </span><span style="font-family:Lucida Console;font-size:85%;">AbstractFountainFactory</span><span style="font-family:Tahoma;font-size:85%;">. </span></p><p><span style="font-family:Tahoma;font-size:85%;">There are ways of getting around the third problem in two main ways. One is by making the AbstractFactory provide default implementations for some of the products (i.e. </span><span style="font-family:Lucida Console;font-size:85%;">Drink</span><span style="font-family:Tahoma;font-size:85%;">s, </span><span style="font-family:Lucida Console;font-size:85%;">Straw</span><span style="font-family:Tahoma;font-size:85%;">s, </span><span style="font-family:Lucida Console;font-size:85%;">Glass</span><span style="font-family:Tahoma;font-size:85%;">es). A second not so frequently used technique (and I think a very poor one) would be handling for null return values from the factory methods.</span></p><p><span style="font-family:Tahoma;font-size:85%;"><a href="http://www.apwebco.com/gofpatterns/creational/AbstractFactory.html#classdiagram">Class Diagram of Abstract Factory Pattern</a></span></p>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com1tag:blogger.com,1999:blog-7267998059814102251.post-57728655148060056592007-08-12T21:23:00.000+06:002007-08-12T21:52:13.924+06:00Factory Method Pattern<p><span style="font-family:Tahoma;font-size:85%;">Consider now that the Client changes her requirements. <a href="http://shamsmi.blogspot.com/2007/08/simple-factory.html">She previously wanted us to make a software for a Pepsi Fountain machine that serves Pepsi, 7UP and Mirinda</a>. She now also wants a Coke Fountain to serve Cocacola, Sprite and Fanta.</span></p><p><span style="font-family:Tahoma;font-size:85%;">The requirement is only a small overhead, but if we want to keep the Simple Factory we created previously we need to do a whole bunch of copy-paste and minor modifications here and there.</span></p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY4oRpnTmsdGXbOPMnAqjS4dgUqDg2iwAObUq4pUcVCOzCaNpiXCKCaFCgtjxwfzWvvH2TyPPqfe8E552m_2lgHh-FQp-ZT4tXdBYiKjNCjziTH3Iwfksp3_J6wEVRjSxjjelkhkLFGVNh/s1600-h/Drink+Images+1.gif"><img id="BLOGGER_PHOTO_ID_5097836388697182802" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY4oRpnTmsdGXbOPMnAqjS4dgUqDg2iwAObUq4pUcVCOzCaNpiXCKCaFCgtjxwfzWvvH2TyPPqfe8E552m_2lgHh-FQp-ZT4tXdBYiKjNCjziTH3Iwfksp3_J6wEVRjSxjjelkhkLFGVNh/s320/Drink+Images+1.gif" border="0" /></a><br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNbAoO3v9rrvNrAYtZDn1uX-iOw9sIJYZFwOvMRDKV-dslDg0kZmATIhwBpwb5ZXYlqsRGiyVttzSctI93q19xoQd63IlYbpVer0V73hr61y0ZUM4CYAppPGgto15JVAPHLg2ff9H8zBGi/s1600-h/factory_method_1.gif"><img id="BLOGGER_PHOTO_ID_5097836053689733666" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNbAoO3v9rrvNrAYtZDn1uX-iOw9sIJYZFwOvMRDKV-dslDg0kZmATIhwBpwb5ZXYlqsRGiyVttzSctI93q19xoQd63IlYbpVer0V73hr61y0ZUM4CYAppPGgto15JVAPHLg2ff9H8zBGi/s320/factory_method_1.gif" border="0" /></a> <span style="font-family:Tahoma;font-size:85%;">This seems to be a fairly good solution, but the two fountain classes are doing almost the same thing, except<br />during the initialization of the drinks. We educate ourselves with another important suggestion of using design patterns: </span><span style="font-family:Tahoma;"><br /><blockquote><p><b>"<i>Depend on Abstractions, not on Concretions</i>"</b></p></blockquote></span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY4oRpnTmsdGXbOPMnAqjS4dgUqDg2iwAObUq4pUcVCOzCaNpiXCKCaFCgtjxwfzWvvH2TyPPqfe8E552m_2lgHh-FQp-ZT4tXdBYiKjNCjziTH3Iwfksp3_J6wEVRjSxjjelkhkLFGVNh/s1600-h/Drink+Images+1.gif"><img id="BLOGGER_PHOTO_ID_5097836388697182802" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY4oRpnTmsdGXbOPMnAqjS4dgUqDg2iwAObUq4pUcVCOzCaNpiXCKCaFCgtjxwfzWvvH2TyPPqfe8E552m_2lgHh-FQp-ZT4tXdBYiKjNCjziTH3Iwfksp3_J6wEVRjSxjjelkhkLFGVNh/s320/Drink+Images+1.gif" border="0" /></a><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOEgBR12f428ljaXEVbuOitq5l-r2UpEvAinbZ2b3VXCme5OuCrtbSCchviAIkJ5x23l4UwRA2C3fC4CBgVRHL_6rLUtu279WIiuPp9hjXoInjvUyl5d1WTBk29StMHvo_9usXZo_kkVv3/s1600-h/factory_method_2.gif"><img id="BLOGGER_PHOTO_ID_5097836062279668274" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOEgBR12f428ljaXEVbuOitq5l-r2UpEvAinbZ2b3VXCme5OuCrtbSCchviAIkJ5x23l4UwRA2C3fC4CBgVRHL_6rLUtu279WIiuPp9hjXoInjvUyl5d1WTBk29StMHvo_9usXZo_kkVv3/s320/factory_method_2.gif" border="0" /></a><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMXl947RybasngBgUpSuoJ9OkQPhAjj77cId-4geAZ4oOllVgwzlOxKxID2Gh5cGPin1ttqZhU0JIvP4KMQa1vPU-sFRDRWIrHAPYEeI6cUQVxiVKtq4Bo-AA7l1ojZQhLE-wUsDR83zMa/s1600-h/factory_method_3.gif"><img id="BLOGGER_PHOTO_ID_5097836062279668290" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMXl947RybasngBgUpSuoJ9OkQPhAjj77cId-4geAZ4oOllVgwzlOxKxID2Gh5cGPin1ttqZhU0JIvP4KMQa1vPU-sFRDRWIrHAPYEeI6cUQVxiVKtq4Bo-AA7l1ojZQhLE-wUsDR83zMa/s320/factory_method_3.gif" border="0" /></a> <span style="font-family:Tahoma;font-size:85%;">Notice how we have introduced a level of abstraction into our Fountains. We can use the </span><span style="font-family:Lucida Console;font-size:85%;">AbstractFountain</span><span style="font-family:Tahoma;font-size:85%;"><br />reference for the two distinct fountains and initialize the reference with the </span><span style="font-family:Lucida Console;font-size:85%;">PepsiFountain </span><span style="font-family:Tahoma;font-size:85%;">or Co</span><span style="font-family:Lucida Console;font-size:85%;">cacolaFountain</span><span style="font-family:Tahoma;font-size:85%;"> as required in our program. Also notice how the common algorithm of getting a drink remains in the </span><span style="font-family:Lucida Console;font-size:85%;">AbstractFountain</span><span style="font-family:Tahoma;font-size:85%;"> while we have created the abstract method </span><span style="font-family:Lucida Console;font-size:85%;">createDrink()</span><span style="font-family:Tahoma;font-size:85%;"> inside our abstract class whose responsibility is to create the </span><span style="font-family:Lucida Console;font-size:85%;">Drink</span><span style="font-family:Tahoma;font-size:85%;">. This method behaves like a factory and is aptly called the '<b>Factory Method</b>'. We have indeed used the Factory method pattern here. The </span><span style="font-family:Lucida Console;font-size:85%;">AbstractFountain</span><span style="font-family:Tahoma;font-size:85%;"> is using its subclasses to specify which objects it creates and hence has no knowledge of which particular drink is being created. This knowledge of which drink is being created is localized at the concrete Fountain implementations namely </span><span style="font-family:Lucida Console;font-size:85%;">PepsiFountain</span><span style="font-family:Tahoma;font-size:85%;"> and </span><span style="font-family:Lucida Console;font-size:85%;">CocacolaFountain</span><span style="font-family:Tahoma;font-size:85%;">.</span><br /><br /><p><span style="font-family:Tahoma;font-size:85%;">More formally we may define the Factory Method as follows:<br /><blockquote>The Factory Method provides a simple decision making class that returns one of several possible subclasses of an abstract base class depending on the data that are provided.<br /></span></blockquote><p><span style="font-family:Tahoma;font-size:85%;"><a href="http://www.apwebco.com/gofpatterns/creational/FactoryMethod.html#classdiagram">Class Diagram of Factory Method Pattern</a></span><br /><br /></p></span>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com0tag:blogger.com,1999:blog-7267998059814102251.post-78989503138259943632007-08-12T20:05:00.000+06:002007-10-06T19:18:12.496+06:00Simple Factory<p><span style="font-family:Tahoma;font-size:85%;">Today we will be understanding the Simple Factory.</span></p><p><span style="font-family:Tahoma;font-size:85%;">So let's first have a simple program to make where we will use the Factory Method pattern.</span></p><p><span style="font-family:Tahoma;font-size:85%;">The requirements of our program are fairly simple:</span></p><p><span style="font-family:Tahoma;font-size:85%;">We have a client and she wants us to make a software for a Pepsi Fountain machine that serves Pepsi, 7UP and Mirinda.</span></p><p><span style="font-family:Tahoma;font-size:85%;">This is really a simple program and we can provide the solution very quickly:</span><br /></p><p align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSfGTqpEq4lT2Fg40kUDgIHtMLeUWemEgku-R9LRLP8lhCGh1obKiJxJMeJhlc26HW73vwxokKi4zeXLDoQW1zLcLVvdf3eNNU-asA91VF0Rna6lACS9qgutWo6t5w2PjqfZU53iz0P-Xz/s1600-h/Pepsi+7Up+Mirinda+1.gif"><img id="BLOGGER_PHOTO_ID_5097818663367152082" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" height="161" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSfGTqpEq4lT2Fg40kUDgIHtMLeUWemEgku-R9LRLP8lhCGh1obKiJxJMeJhlc26HW73vwxokKi4zeXLDoQW1zLcLVvdf3eNNU-asA91VF0Rna6lACS9qgutWo6t5w2PjqfZU53iz0P-Xz/s320/Pepsi+7Up+Mirinda+1.gif" border="0" /></a></p><br /><p><img id="BLOGGER_PHOTO_ID_5097831187491787234" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGcB_wZVckez4t1VSwtePnSgH8Lnn6TKRTNd_KSzAktSmWb9gITPlSuDQnrZnlFNUIMRr3LLBUcEcBCr93ORPnpyUQJ4WfhB2rNTIJGurDA_rcWhlgFm4shy270c9L0fuhUbXnEuq0rkkj/s320/simple_factory_1.gif" border="0" /><span style="font-family:Tahoma;font-size:85%;">Notice the segment in bold. If we have to add another drink, say Diet Pepsi, to this Fountain we have created we would need to add another if-else block and another constant (if we wanted to maintain a minimum<br />standard of good practice :) ).</span></p><p><span style="font-family:Tahoma;font-size:85%;">It is time to get familiar with one of the more important suggestions while using design patterns: </span><br /><br /><b>"<i>Encapsulate what varies</i>"</b></p><p><span style="font-family:Tahoma;font-size:85%;">We notice that the bold block in the PepsiFountain class is the one likely to vary when the client changes her<br />requirements. So it is best to remove that block from the execution block in the method.There are quite a few alternatives for us. One of the more commonly chosen techniques is to remove that segment and move it to a utility class with a static method as follows:</span><br /><p align="center"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSfGTqpEq4lT2Fg40kUDgIHtMLeUWemEgku-R9LRLP8lhCGh1obKiJxJMeJhlc26HW73vwxokKi4zeXLDoQW1zLcLVvdf3eNNU-asA91VF0Rna6lACS9qgutWo6t5w2PjqfZU53iz0P-Xz/s1600-h/Pepsi+7Up+Mirinda+1.gif"><img id="BLOGGER_PHOTO_ID_5097818663367152082" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSfGTqpEq4lT2Fg40kUDgIHtMLeUWemEgku-R9LRLP8lhCGh1obKiJxJMeJhlc26HW73vwxokKi4zeXLDoQW1zLcLVvdf3eNNU-asA91VF0Rna6lACS9qgutWo6t5w2PjqfZU53iz0P-Xz/s320/Pepsi+7Up+Mirinda+1.gif" border="0" /></a><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidMU-rX-Pa3xzxsx_epYOJnlalIQjjW81H8Hz8xZ_KCYzBpAgPZMD7EOuUnADBH29XZ3oxVPp0XplfglVoIlk167EufenuPx8JSs_N-jOPrncraaOm8S2-7gboufiVlGgjWFGo_Vi5Zm6W/s1600-h/simple_factory_2.gif"><img id="BLOGGER_PHOTO_ID_5097834335702815234" style="DISPLAY: block; MARGIN: 0px auto 10px; CURSOR: hand; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidMU-rX-Pa3xzxsx_epYOJnlalIQjjW81H8Hz8xZ_KCYzBpAgPZMD7EOuUnADBH29XZ3oxVPp0XplfglVoIlk167EufenuPx8JSs_N-jOPrncraaOm8S2-7gboufiVlGgjWFGo_Vi5Zm6W/s320/simple_factory_2.gif" border="0" /></a></p><p><br /><span style="font-family:Tahoma;font-size:85%;">What we've just created is known as a 'Simple Factory'. It really isn't a design pattern and is very often confused with the <a href="http://shamsmi.blogspot.com/2007/08/factory-method-pattern.html">Factory Method Pattern</a>. Simple Factories are very commonly used techniques and should be used when as the name suggests requirements are fairly simple :).</span></p>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com3tag:blogger.com,1999:blog-7267998059814102251.post-84704682016813091082007-07-29T21:17:00.000+06:002007-07-29T22:02:10.328+06:00Comfortable Introduction to Design Patterns<p class="MsoNormal" style="LINE-HEIGHT: 150%"><span style="color:#333333;"><b><u><span style="LINE-HEIGHT: 150%;font-family:Tahoma;font-size:130%;" >Design Pattern</span></u></b><br /></span></p><p class="MsoNormal"><span style="font-family:Tahoma;color:#333333;">Over the last few days we have been having design pattern sessions for everyone at our firm. So I thought it would be an opportune time to let everyone know about my understanding of design patterns. Over the course of time I also intend to write about a couple of design patterns.</span></p><p class="MsoNormal"><span style="font-family:Tahoma;color:#333333;">So what actually is a pattern and what actually is a design pattern. The dictionary definition of a ‘pattern’ is as follows:</span></p><span style="font-family:Tahoma;"><blockquote><span style="font-family:Tahoma;color:#333333;">Pattern (noun): model/example which<br />you should copy.</span></blockquote><p class="MsoNormal"></span><span style="font-family:Tahoma;color:#333333;">We apply patterns in many facets of our life. It is only but obvious then that we should apply patterns even in <b>software development</b>. We may apply <b>patterns</b> while <b>designing</b> a solution to a particular problem we have. These patterns are what we call Design Patterns in software development. More formally a design pattern can be defined as follows:</span></p><div class="Section1"><span style="font-family:Verdana;"><blockquote><span style="font-family:Verdana;"><a href="http://www.onjava.com/pub/a/onjava/2002/01/16/patterns.html?page=1"><span style="color:#333333;">A design pattern is simply </span></a><a href="http://www.onjava.com/pub/a/onjava/2002/01/16/patterns.html?page=1"><span style="color:#333333;"><i>a description of a recurring<br />solution to a problem, given a context</i>.</span></a></span></blockquote></span></div><div class="Section1"><span style="font-family:Tahoma;color:#333333;">Design patterns are language-independent strategies for solving common object-oriented design problems. Hence they should be equally applicable no matter which object-oriented language you use. Design patterns are not idioms or algorithms or components.</span></div><div class="Section1"><br /><span style="font-family:Tahoma;color:#333333;">Before beginning to read more on the various design patterns I think we should realize that these patterns as such are not really invented by anyone in particular. They have just evolved over time by different people (software engineers) who faced various problem and come up with solutions to them. In fact it is possible that we have been using many design patterns without knowing their names. For example I had been using singletons, strategy and facades even before we had started the sessions in my firm. </span></div><div class="Section1"><br /><span style="font-family:Tahoma;color:#333333;">Though I was applying some design patterns without knowing them I actually found benefits from a formal study of them. For one having these discussions helped me better understand what these design patterns actually are and how best to apply them. It has also helped improve out vocabulary and communication between team members. In fact we even use the<br />names of many of the design patterns in our everyday vocabulary in the office, for e.g. delegating responsibilities and giving proxies. Most importantly, a design pattern facilitates change requests from your client, a given during the life cycle of any software.</span></div><div class="Section1"><br /><span style="font-family:Tahoma;color:#333333;">At first reading through design patterns and actually applying those in our designs and solutions might seem like a lot of hassle. But in the long run they really pay off. In fact one of the goals of design patterns is to make our software design reusable. Using the right design pattern in our solution results in the final product being more flexible and the inner components being reusable. Notice that I used the word ‘right’ because there are so many design patterns and it is easy to misapply them.</span></div><div class="Section1"><br /><span style="font-family:Tahoma;color:#333333;">Hence while reading on a design pattern one should be careful to note the following:</span></div><div class="Section1"><span style="color:#333333;"></span></div><div class="Section1"><span dir="ltr"><b><span style="font-family:Tahoma;color:#333333;">Name of the pattern</span></b></span><span style="font-family:Tahoma;color:#333333;">:<br />One should definitely know the design pattern he is going to be using to avoid miscommunication with others</span></div><div class="Section1"><span style="font-family:Tahoma;"><span style="FONT: 100% 'Times New Roman'"><br /></span></span><span style="color:#333333;"><span dir="ltr"><b><span style="font-family:Tahoma;">Scenario when to use the pattern</span></b></span><span style="font-family:Tahoma;">: </span></span></div><div class="Section1"><span style="font-family:Tahoma;color:#333333;">As I said there are so many patterns and it is easy to misuse them. A clear understanding of the problem scenario and when to use them is critical to gaining the maximum benefit of using a particular pattern. Often there are many variations/multiple ways to implement a particular pattern. A good understanding of the problem scenario helps one take the correct decision<br />while facing these choices.</span></div><div class="Section1"><br /><span dir="ltr"><b><span style="font-family:Tahoma;color:#333333;">Consequence of using the pattern: </span></b></span></div><div class="Section1"><span style="font-family:Tahoma;color:#333333;">One should also realize the advantages and disadvantages of using a particular pattern. Often a clear understanding of these help eliminate choices when we are faced with choices amongst multiple design patterns for a particular problem. </span></div><div class="Section1"><br /><span style="font-family:Tahoma;color:#333333;">Design patterns can be classified in two ways mainly:</span></div><div class="Section1"><br /><strong><span style="color:#333333;"><span style="font-family:Tahoma;">1)<span style="FONT: 100% 'Times New Roman'"> </span></span><span dir="ltr"><span style="font-family:Tahoma;">What the Pattern does</span></span></span></strong></div><div class="Section1"><br /><span dir="ltr"><b><span style="font-family:Tahoma;color:#333333;">Creational Patterns</span></b></span><span style="font-family:Tahoma;color:#333333;">:<br />They deal with various mechanisms of object creation. Examples include Abstract Factory, Factory Method, Singleton, Prototype and Builder patterns.</span></div><div class="Section1"><br /><span dir="ltr"><b><span style="font-family:Tahoma;color:#333333;">Structural Patterns</span></b></span><span style="font-family:Tahoma;color:#333333;">:<br />They deal with the structure i.e. composition of classes and objects. Common examples include Adapter, Composite, Bridge, Decorator, and Proxy patterns.</span></div><div class="Section1"><br /><span style="color:#333333;"><span dir="ltr"><b><span style="font-family:Tahoma;">Behavioral Patterns</span></b></span><span style="font-family:Tahoma;">: </span></span></div><div class="Section1"><span style="font-family:Tahoma;color:#333333;">They deal with means of communication between objects. Common examples include Strategy, Observer, and Visitor patterns.</span></div><div class="Section1"><br /><span style="font-family:Tahoma;color:#333333;"></span></div><div class="Section1"><strong><span style="color:#333333;"><span style="font-family:Tahoma;">2)<span style="FONT: 100% 'Times New Roman'"> </span></span><span dir="ltr"><span style="font-family:Tahoma;">What kind of relationships it focuses on</span></span></span></strong></div><div class="Section1"><br /><span dir="ltr"><b><span style="font-family:Tahoma;color:#333333;">Class Patterns</span></b></span><span style="font-family:Tahoma;color:#333333;">:<br />They deal with inheritance, i.e. the ‘is a’ relationship of classes. Examples include Factory Method pattern.</span></div><div class="Section1"><br /><span style="color:#333333;"><span dir="ltr"><b><span style="font-family:Tahoma;">Object Patterns</span></b></span><span style="font-family:Tahoma;">: </span></span></div><div class="Section1"><span style="font-family:Tahoma;color:#333333;">They deal with relationships between objects, i.e. the ‘has a’ relationship of objects. Examples include the Abstract Factory</span></div><div class="Section1"><br /><span style="font-family:Tahoma;color:#333333;">Just another point before ending today is that one needs to read as many design patterns as possible. It is because design patterns are rarely used in isolation. More commonly they are always used in conjunction with other design patterns.</span></div><div class="Section1"><br /><span style="font-family:Tahoma;color:#333333;">Check back again soon. I hope to write on the Abstract Factory and Factory Method patterns soon. </span></div><div class="Section1"><span style="color:#333333;"></span></div>Shamshttp://www.blogger.com/profile/10301627897367423203noreply@blogger.com4