{"id":54161,"date":"2016-03-25T10:00:48","date_gmt":"2016-03-25T08:00:48","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=54161"},"modified":"2016-03-25T09:14:03","modified_gmt":"2016-03-25T07:14:03","slug":"introducing-delegate-pattern","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html","title":{"rendered":"Introducing The Delegate Pattern"},"content":{"rendered":"<ul>\n<li><strong>Delegate:<\/strong> a person who is chosen or elected to vote or act for others \u2013\u00a0<a href=\"http:\/\/www.merriam-webster.com\/dictionary\/delegate\" target=\"_blank\">Merriam-Webster<\/a>.<\/li>\n<li><strong>Delegate pattern:<\/strong> In software engineering, the delegation pattern is a design pattern in object-oriented programming where an object, instead of performing one of its stated tasks, delegates that task to an associated helper object \u2013\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Delegation_pattern\" target=\"_blank\">Wikipedia<\/a>.<\/li>\n<li><strong><em>Make things as simple as possible, but not simpler \u2013<\/em><\/strong><em>\u00a0Albert Einstein, paraphrased<\/em><strong><em>.<\/em><\/strong><\/li>\n<\/ul>\n<p><a href=\"http:\/\/projects.spring.io\/spring-batch\/\" target=\"_blank\">Spring Batch<\/a> is an important tool in the Enterprise Java toolkit. It provides great functionality out of the box, especially for reading and writing data from different sources. We have provided <a href=\"https:\/\/keyholesoftware.com\/tag\/spring-batch\/\" target=\"_blank\">several articles in this blog<\/a> introducing Spring Batch. If you are not familiar with Spring Batch and the Reader, Processor, Writer Tasklet, please take a moment and review those.<\/p>\n<p>The paraphrased quote I use above is important to me. One of the things I try to do is keep the code I deliver as maintainable as possible. I want it to work, and work well, but code I check in today, will be maintained by somebody at some future date. Keeping the code as simple as possible is one way of ensuring that the code can be easily maintainable.<\/p>\n<p>So what happens when you have a complicated data source that you have to process?<\/p>\n<p>We find that often input files we have to process are not as simple as one record per line. Often we have multiple lines in the file describe just one record.<\/p>\n<p>For instance:<\/p>\n<pre class=\" brush:bash\">HKaren Traviss\r\nLAB00KW3VG2G\r\nLI0345478274\r\nLI0345511131\r\nF00000003\r\nHJim Butcher\r\nLI0451457811\r\nF00000001\r\nHDave Duncan\r\nLI0380791277\r\nLI0345352912\r\nF00000002\r\nHRik Scarborough\r\nLI9999999999\r\nF00000001<\/pre>\n<p>Here we have a file that contains four records across fifteen lines. Each record starts with a Header line, contains one or more Body lines, and ends on a Footer. The Header contains a line type (H for header), and a name. The line also contains a line type (L), the type of lookup, in this example either a ISBN or an Amazon code, and the key to look up a book. The footer contains, again, a line type and the number of records in this block.<\/p>\n<p>Using a standard Reader, each line would be read then passed on to the Processor who would then have to determine what kind of line it is dealing with. The Processor would then have to retain the information from each Header as it processed each Body line, until a Footer was processed. The Writer would then have to be aware of each line that the Processor sent, and whether it should be written. This is complex, in part, because multiple objects have to be aware of how the file is read in, instead of the Processor only caring about a single object, and the Writer only concerned with writing what it\u2019s been given.<\/p>\n<p>Instead, lets introduce the Delegate pattern to the Reader and let it handle creating the entire record. Since we have information from multiple lines as well as a Header and Footer that we will use to create each record, we will have to pass the Processor a list of records. The observant among you will have noticed that each Record contains either an ISBN or Amazon book notation and that could be used to lookup the Author, which is also contained in the Header. In a real life example, this type of redundancy may nor may not happen.<\/p>\n<p>Let\u2019s wrap the output in another object to make it easier to work with.<\/p>\n<pre class=\" brush:bash\">public class OrderReaderStep implements ItemReader&lt;OrderList&gt; {\r\n\r\n    private static final Logger logger = LoggerFactory.getLogger(OrderReaderStep.class);\r\n    private FlatFileItemReader\r\n&lt;FieldSet&gt; delegate;\r\n    private static final String FOOTER = \"F*\";\r\n    private static final String BODY = \"L*\";\r\n    private static final String HEADER = \"H*\";\r\n\r\n    @BeforeStep\r\n    public void beforeStep(StepExecution stepExecution) {\r\n        delegate = new FlatFileItemReader&lt;&gt;();\r\n\r\n        delegate.setResource(new ClassPathResource(\"orders.txt\"));\r\n\r\n        final DefaultLineMapper\r\n&lt;FieldSet&gt; defaultLineMapper = new DefaultLineMapper&lt;&gt;();\r\n        final PatternMatchingCompositeLineTokenizer orderFileTokenizer = new PatternMatchingCompositeLineTokenizer();\r\n        final Map&lt;String, LineTokenizer&gt; tokenizers = new HashMap&lt;&gt;();\r\n        tokenizers.put(HEADER, buildHeaderTokenizer());\r\n        tokenizers.put(BODY, buildBodyTokenizer());\r\n        tokenizers.put(FOOTER, buildFooterTokenizer());\r\n        orderFileTokenizer.setTokenizers(tokenizers);\r\n        defaultLineMapper.setLineTokenizer(orderFileTokenizer);\r\n        defaultLineMapper.setFieldSetMapper(new PassThroughFieldSetMapper());\r\n\r\n        delegate.setLineMapper(defaultLineMapper);\r\n\r\n        delegate.open(stepExecution.getExecutionContext());\r\n    }\r\n\r\n    @AfterStep\r\n    public void afterStep(StepExecution stepExecution) {\r\n        delegate.close();\r\n    }\r\n\r\n    @Override\r\n    public OrderList read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {\r\n        logger.info(\"start read\");\r\n\r\n        OrderList record = null;\r\n\r\n        FieldSet line;\r\n        List&lt;Order&gt; bodyList = new ArrayList&lt;&gt;();\r\n        while ((line = delegate.read()) != null) {\r\n            String prefix = line.readString(\"lineType\");\r\n            if (prefix.equals(\"H\")) {\r\n                record = new OrderList();\r\n                record.setName(line.readString(\"name\"));\r\n            } else if (prefix.equals(\"L\")) {\r\n                Order order = new Order();\r\n                order.setLookup(line.readString(\"lookupKey\"));\r\n                order.setLookupType(line.readString(\"keyType\"));\r\n                bodyList.add(order);\r\n            } else if (prefix.equals(\"F\")) {\r\n                if (record != null) {\r\n                    if (line.readLong(\"count\") != bodyList.size()) {\r\n                        throw new ValidationException(\"Size does not match file count\");\r\n                    }\r\n                    record.setOrders(bodyList);\r\n                }\r\n                break;\r\n            }\r\n\r\n        }\r\n        logger.info(\"end read\");\r\n        return record;\r\n    }\r\n\r\n    private LineTokenizer buildBodyTokenizer() {\r\n        FixedLengthTokenizer tokenizer = new FixedLengthTokenizer();\r\n\r\n        tokenizer.setColumns(new Range[]{ \/\/\r\n            new Range(1, 1), \/\/ lineType\r\n            new Range(2, 2), \/\/ keyType\r\n            new Range(3, 12) \/\/ lookup key\r\n        });\r\n\r\n        tokenizer.setNames(new String[]{ \/\/\r\n            \"lineType\",\r\n            \"keyType\",\r\n            \"lookupKey\"\r\n        }); \/\/\r\n        tokenizer.setStrict(false);\r\n        return tokenizer;\r\n    }\r\n\r\n    private LineTokenizer buildFooterTokenizer() {\r\n        FixedLengthTokenizer tokenizer = new FixedLengthTokenizer();\r\n\r\n        tokenizer.setColumns(new Range[]{ \/\/\r\n            new Range(1, 1), \/\/ lineType\r\n            new Range(2, 9) \/\/ count\r\n        });\r\n\r\n        tokenizer.setNames(new String[]{ \/\/\r\n            \"lineType\",\r\n            \"count\"\r\n        }); \/\/\r\n        tokenizer.setStrict(false);\r\n        return tokenizer;\r\n    }\r\n\r\n    private LineTokenizer buildHeaderTokenizer() {\r\n        FixedLengthTokenizer tokenizer = new FixedLengthTokenizer();\r\n\r\n        tokenizer.setColumns(new Range[]{ \/\/\r\n            new Range(1, 1), \/\/ lineType\r\n            new Range(2, 20), \/\/ name\r\n        });\r\n\r\n        tokenizer.setNames(new String[]{ \/\/\r\n            \"lineType\",\r\n            \"name\"\r\n        }); \/\/\r\n        tokenizer.setStrict(false);\r\n        return tokenizer;\r\n    }\r\n\r\n}<\/pre>\n<p>This Reader implements the ItemReader interface. This gives us a read method that is called by the job until it returns a null, or in case of a error, throws an exception. In our Reader, we declare another Reader, this one is a FlatFileItemReader. This is our Delegate, or the Object that has been selected to perform a function on for us. Our read method will loop on the Delegate\u2019s read until a Footer is read. It will then bundle the entire record into its wrapper and pass it on to the Processor.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>The Delegate Reader must be opened before it can be used, and then should be closed only when it is done. I open it here in the BeforeStep since I have to initialize it and set it up here. I could also implement the containing reader as an ItemStreamReader and use the open, close, as well as update, methods that Interface gives us.<\/p>\n<p>Returning a simplified object to the Processor allows us to greatly simplify the Processor:<\/p>\n<pre class=\" brush:bash\">@Override\r\npublic List&lt;BookList&gt; process(OrderList orderList) throws Exception {\r\n    logger.info(\"process\");\r\n    List&lt;BookList&gt; books = new ArrayList&lt;&gt;();\r\n    for (Order order : orderList.getOrders()) {\r\n        BookList bl = doProcessing(orderList.getName(), order);\r\n        books.add(bl);\r\n    }\r\n    return books;\r\n}<\/pre>\n<p>The doProcessing method can contain the business logic for this Job and needs to create a valid BookList object. Since we are dealing with multiple records, the process will create multiple BookLists that can be returned, and passed on to the Writer. I\u2019ll leave it to you to fill in the rest of this object, but it is just a standard ItemProcessor. The Processor does not have to retain record information between calls, so the programmer can concentrate on the business logic.<\/p>\n<p>Our Writer implements the ItemStreamWriter. This gives us more methods than the ItemWriter would, but if you prefer using ItemWriter similarly to the way we did the Reader, make sure you open the Delegate in the BeforeStep and close it in the AfterStep.<\/p>\n<p>Using a Delegate in the Writer gives us the ability to walk thorough the List the Writer receives from the Reader and Process.<\/p>\n<pre class=\" brush:bash\">public class ListWriter implements ItemStreamWriter&lt;List&lt;BookList&gt;&gt; {\r\n\r\n    private static final Logger logger = LoggerFactory.getLogger(ListWriter.class);\r\n\r\n    private FlatFileItemWriter&lt;BookList&gt; delegate;\r\n\r\n    @BeforeStep\r\n    public void beforeStep(StepExecution stepExecution) {\r\n        delegate = new FlatFileItemWriter&lt;&gt;();\r\n        delegate.setResource(new FileSystemResource(\"booklist.csv\"));\r\n        delegate.setShouldDeleteIfEmpty(true);\r\n        delegate.setAppendAllowed(true);\r\n\r\n        DelimitedLineAggregator&lt;BookList&gt; dla = new DelimitedLineAggregator&lt;&gt;();\r\n        dla.setDelimiter(\",\");\r\n        BeanWrapperFieldExtractor&lt;BookList&gt; fieldExtractor = new BeanWrapperFieldExtractor&lt;&gt;();\r\n        fieldExtractor.setNames(new String[]{\"bookName\", \"author\"});\r\n        dla.setFieldExtractor(fieldExtractor);\r\n        delegate.setLineAggregator(dla);\r\n    }\r\n\r\n    @Override\r\n    public void close() throws ItemStreamException {\r\n        delegate.close();\r\n    }\r\n\r\n    @Override\r\n    public void open(ExecutionContext ec) throws ItemStreamException {\r\n        delegate.open(ec);\r\n    }\r\n\r\n    @Override\r\n    public void update(ExecutionContext ec) throws ItemStreamException {\r\n        delegate.update(ec);\r\n    }\r\n\r\n    @Override\r\n    public void write(List&lt;? extends List&lt;BookList&gt;&gt; list) throws Exception {\r\n        logger.info(\"write\");\r\n        for (List&lt;BookList&gt; bookList : list) {\r\n            delegate.write(bookList);\r\n        }\r\n    }\r\n\r\n}<\/pre>\n<p>This gives us the following output:<\/p>\n<pre class=\" brush:bash\">Going Grey,Karen Traviss\r\nHard Contact,Karen Traviss\r\n501st,Karen Traviss\r\nStorm Front,Jim Butcher\r\nLord of the Fire Lands,Dave Duncan\r\nThe Reluctant Swordsman,Dave Duncan\r\nWolfbrander Series Unpublished,Rik Scarborough<\/pre>\n<p>So what happens if it\u2019s a little more complicated and the input file does not contain a footer?<\/p>\n<p>The logical record still starts at the Header line, but ends at the line before the next Header. In our previous example, the system would have to read the next line before it knows it\u2019s done, and then have some complicated logic to retain that information for the next go-round.<\/p>\n<pre class=\" brush:bash\">HKaren Traviss\r\nLAB00KW3VG2G\r\nLI0345478274\r\nLI0345511131\r\nHJim Butcher\r\nLI0451457811\r\nHDave Duncan\r\nLI0380791277\r\nLI0345352912\r\nHRik Scarborough\r\nLI9999999999<\/pre>\n<p>Asking our current writer to read ahead and hold on to that record during the next call is unnecessarily complex, which leads to maintenance headaches. However, we can simplify this by using the PeekableItemReader:<\/p>\n<pre class=\" brush:bash\">class OrderReaderStep2 implements ItemStreamReader&lt;OrderList&gt; {\r\n\r\n    private static final String BODY = \"L*\";\r\n    private static final String HEADER = \"H*\";\r\n    private static final Logger logger = LoggerFactory.getLogger(OrderReaderStep2.class);\r\n    private SingleItemPeekableItemReader\r\n&lt;FieldSet&gt; delegate;\r\n\r\n    @BeforeStep\r\n    public void beforeStep(StepExecution stepExecution) {\r\n        FlatFileItemReader fileReader = new FlatFileItemReader&lt;&gt;();\r\n\r\n        fileReader.setResource(new ClassPathResource(\"orders2.txt\"));\r\n\r\n        final DefaultLineMapper\r\n&lt;FieldSet&gt; defaultLineMapper = new DefaultLineMapper&lt;&gt;();\r\n        final PatternMatchingCompositeLineTokenizer orderFileTokenizer = new PatternMatchingCompositeLineTokenizer();\r\n        final Map&lt;String, LineTokenizer&gt; tokenizers = new HashMap&lt;&gt;();\r\n        tokenizers.put(HEADER, buildHeaderTokenizer());\r\n        tokenizers.put(BODY, buildBodyTokenizer());\r\n        orderFileTokenizer.setTokenizers(tokenizers);\r\n        defaultLineMapper.setLineTokenizer(orderFileTokenizer);\r\n        defaultLineMapper.setFieldSetMapper(new PassThroughFieldSetMapper());\r\n\r\n        fileReader.setLineMapper(defaultLineMapper);\r\n\r\n        delegate = new SingleItemPeekableItemReader&lt;&gt;();\r\n        delegate.setDelegate(fileReader);\r\n    }\r\n\r\n    @Override\r\n    public void close() throws ItemStreamException {\r\n        delegate.close();\r\n    }\r\n\r\n    @Override\r\n    public void open(ExecutionContext ec) throws ItemStreamException {\r\n        delegate.open(ec);\r\n    }\r\n\r\n    @Override\r\n    public OrderList read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {\r\n        logger.info(\"start read\");\r\n\r\n        OrderList record = null;\r\n\r\n        FieldSet line;\r\n        List&lt;Order&gt; bodyList = new ArrayList&lt;&gt;();\r\n        while ((line = delegate.read()) != null) {\r\n            String prefix = line.readString(\"lineType\");\r\n            if (prefix.equals(\"H\")) {\r\n                record = new OrderList();\r\n                record.setName(line.readString(\"name\"));\r\n            } else if (prefix.equals(\"L\")) {\r\n                Order order = new Order();\r\n                order.setLookup(line.readString(\"lookupKey\"));\r\n                order.setLookupType(line.readString(\"keyType\"));\r\n                bodyList.add(order);\r\n            }\r\n\r\n            FieldSet nextLine = delegate.peek();\r\n            if (nextLine == null || nextLine.readString(\"lineType\").equals(\"H\")) {\r\n                record.setOrders(bodyList);\r\n                break;\r\n            }\r\n\r\n        }\r\n        logger.info(\"end read\");\r\n        return record;\r\n    }\r\n\r\n    @Override\r\n    public void update(ExecutionContext ec) throws ItemStreamException {\r\n        delegate.update(ec);\r\n    }\r\n\r\n    private LineTokenizer buildBodyTokenizer() {\r\n        FixedLengthTokenizer tokenizer = new FixedLengthTokenizer();\r\n\r\n        tokenizer.setColumns(new Range[]{ \/\/\r\n            new Range(1, 1), \/\/ lineType\r\n            new Range(2, 2), \/\/ keyType\r\n            new Range(3, 12) \/\/ lookup key\r\n        });\r\n\r\n        tokenizer.setNames(new String[]{ \/\/\r\n            \"lineType\",\r\n            \"keyType\",\r\n            \"lookupKey\"\r\n        }); \/\/\r\n        tokenizer.setStrict(false);\r\n        return tokenizer;\r\n    }\r\n\r\n    private LineTokenizer buildHeaderTokenizer() {\r\n        FixedLengthTokenizer tokenizer = new FixedLengthTokenizer();\r\n\r\n        tokenizer.setColumns(new Range[]{ \/\/\r\n            new Range(1, 1), \/\/ lineType\r\n            new Range(2, 20), \/\/ name\r\n        });\r\n\r\n        tokenizer.setNames(new String[]{ \/\/\r\n            \"lineType\",\r\n            \"name\"\r\n        }); \/\/\r\n        tokenizer.setStrict(false);\r\n        return tokenizer;\r\n    }\r\n\r\n}<\/pre>\n<p>This time I do implement the containing Reader as an ItemStreamReader to show you the difference. This could have been implemented as an ItemReader as our previous one was.<\/p>\n<p>The PeekableItemReader allows us to look ahead to the next record to see if we have reached the end of the record, or the end of the file. The same Processor and Writer can then be used to produce the same output as before.<\/p>\n<h2>Final Thoughts<\/h2>\n<p>At first glance, the Delegate Pattern may not seem as simple as using a single Reader or Writer. There is more configuration for both of these objects. But my favorite paraphrased quote says to be as simple as possible, and no simpler. A slightly more complex Reader and Writer will make your Processor much simpler, and help with maintenance down the road.<\/p>\n<p>Code well, my friend.<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/keyholesoftware.com\/2016\/03\/23\/introducing-the-delegate-pattern\/\">Introducing The Delegate Pattern<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/join-us\/jcg\/\">JCG partner<\/a> Rik Scarborough at the <a href=\"http:\/\/keyholesoftware.com\/\">Keyhole Software<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Delegate: a person who is chosen or elected to vote or act for others \u2013\u00a0Merriam-Webster. Delegate pattern: In software engineering, the delegation pattern is a design pattern in object-oriented programming where an object, instead of performing one of its stated tasks, delegates that task to an associated helper object \u2013\u00a0Wikipedia. Make things as simple as &hellip;<\/p>\n","protected":false},"author":471,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[145,30,691],"class_list":["post-54161","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-design-patterns","tag-spring","tag-spring-batch"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Introducing The Delegate Pattern - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Delegate: a person who is chosen or elected to vote or act for others \u2013\u00a0Merriam-Webster. Delegate pattern: In software engineering, the delegation pattern\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Introducing The Delegate Pattern - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Delegate: a person who is chosen or elected to vote or act for others \u2013\u00a0Merriam-Webster. Delegate pattern: In software engineering, the delegation pattern\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:author\" content=\"http:\/\/facebook.com\/keyholesoftware\" \/>\n<meta property=\"article:published_time\" content=\"2016-03-25T08:00:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Keyhole Software\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@http:\/\/twitter.com\/keyholesoftware\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Keyhole Software\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html\"},\"author\":{\"name\":\"Keyhole Software\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/621b02d9eb189f8d1aec83b2bcfa14d6\"},\"headline\":\"Introducing The Delegate Pattern\",\"datePublished\":\"2016-03-25T08:00:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html\"},\"wordCount\":1145,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Design Patterns\",\"Spring\",\"Spring Batch\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html\",\"name\":\"Introducing The Delegate Pattern - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2016-03-25T08:00:48+00:00\",\"description\":\"Delegate: a person who is chosen or elected to vote or act for others \u2013\u00a0Merriam-Webster. Delegate pattern: In software engineering, the delegation pattern\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/03\\\/introducing-delegate-pattern.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Introducing The Delegate Pattern\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/621b02d9eb189f8d1aec83b2bcfa14d6\",\"name\":\"Keyhole Software\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g\",\"caption\":\"Keyhole Software\"},\"description\":\"Keyhole is a midwest-based consulting firm with a tight-knit technical team. We work primarily with Java, JavaScript and .NET technologies, specializing in application development. We love the challenge that comes in consulting and blog often regarding some of the technical situations and technologies we face.\",\"sameAs\":[\"http:\\\/\\\/keyholesoftware.com\\\/\",\"http:\\\/\\\/facebook.com\\\/keyholesoftware\",\"http:\\\/\\\/linkedin.com\\\/company\\\/keyhole-software\",\"https:\\\/\\\/x.com\\\/http:\\\/\\\/twitter.com\\\/keyholesoftware\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/keyhole-software\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Introducing The Delegate Pattern - Java Code Geeks","description":"Delegate: a person who is chosen or elected to vote or act for others \u2013\u00a0Merriam-Webster. Delegate pattern: In software engineering, the delegation pattern","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html","og_locale":"en_US","og_type":"article","og_title":"Introducing The Delegate Pattern - Java Code Geeks","og_description":"Delegate: a person who is chosen or elected to vote or act for others \u2013\u00a0Merriam-Webster. Delegate pattern: In software engineering, the delegation pattern","og_url":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_author":"http:\/\/facebook.com\/keyholesoftware","article_published_time":"2016-03-25T08:00:48+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Keyhole Software","twitter_card":"summary_large_image","twitter_creator":"@http:\/\/twitter.com\/keyholesoftware","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Keyhole Software","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html"},"author":{"name":"Keyhole Software","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/621b02d9eb189f8d1aec83b2bcfa14d6"},"headline":"Introducing The Delegate Pattern","datePublished":"2016-03-25T08:00:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html"},"wordCount":1145,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Design Patterns","Spring","Spring Batch"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html","url":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html","name":"Introducing The Delegate Pattern - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2016-03-25T08:00:48+00:00","description":"Delegate: a person who is chosen or elected to vote or act for others \u2013\u00a0Merriam-Webster. Delegate pattern: In software engineering, the delegation pattern","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2016\/03\/introducing-delegate-pattern.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Introducing The Delegate Pattern"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/621b02d9eb189f8d1aec83b2bcfa14d6","name":"Keyhole Software","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g","caption":"Keyhole Software"},"description":"Keyhole is a midwest-based consulting firm with a tight-knit technical team. We work primarily with Java, JavaScript and .NET technologies, specializing in application development. We love the challenge that comes in consulting and blog often regarding some of the technical situations and technologies we face.","sameAs":["http:\/\/keyholesoftware.com\/","http:\/\/facebook.com\/keyholesoftware","http:\/\/linkedin.com\/company\/keyhole-software","https:\/\/x.com\/http:\/\/twitter.com\/keyholesoftware"],"url":"https:\/\/www.javacodegeeks.com\/author\/keyhole-software"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/54161","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/471"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=54161"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/54161\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=54161"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=54161"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=54161"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}