[소프트웨어 설계 패턴 C# 동강] 21. 장식자 패턴 (Decorator Pattern) 구현 실습

seen from United States

seen from United States

seen from Malaysia

seen from Netherlands
seen from Malaysia
seen from Malaysia

seen from Netherlands

seen from United Kingdom
seen from China
seen from China
seen from United States
seen from Türkiye
seen from United States
seen from China

seen from China
seen from China

seen from United Kingdom
seen from China
seen from United States
seen from Germany
[소프트웨어 설계 패턴 C# 동강] 21. 장식자 패턴 (Decorator Pattern) 구현 실습

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
[소프트웨어 설계 패턴 C# 동강] 20. 장식자 패턴 (Decorator Pattern) 시나리오 및 클래스 다이어그램
Decorator pattern
One of the design patterns
= “a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class”
to be added to an individual object,
either statically or dynamically
without affecting the behavior of other objects from the same class.
Implementing Decorators In JavaScript Using Closures
Sometimes functionality needs to be added to a each each method of an object. Here is the object:
var objectA = { method1: function() { console.log('running method 1'); }, method2: function() { console.log('running method 2'); }, method3: function() { console.log('running method 3'); } };
The simplest way to deal with this is to insert a new method that runs the desired functionality then a specified method from the object passed in as an argument. But this would require modifying every part of the code that calls method1, method2 or method3. So a call to the new method would have to be inserted for each function which is clumsy:
var objectA = { methodPrepend: function() { console.log('prepend'); }, method1: function() { objectA.methodPrepend(); console.log('running method 1'); }, method2: function() { objectA.methodPrepend(); console.log('running method 2'); }, method3: function() { objectA.methodPrepend(); console.log('running method 3'); } }; objectA.method1(); // prepend\n running method 1 objectA.method2(); // prepend\n running method 2 objectA.method3(); // prepend\n running method 3
Fortunately, JavaScript methods (which are just object properties) can be updated at run time. So it is possible to wrap all methods in the object with a decorator function:
var decorate = function(obj, toRunFirst) { for (var property in obj){ // wrap all functions if (typeof(obj[property]) === "function"){ // Need to ensure that the closure scope is unique for each property (function(property) { var oldFunc = obj[property]; obj[property] = function() { toRunFirst(); return oldFunc.apply(null, Array.prototype.slice.call(arguments)); } })(property); } } }; var objectA = { methodPrepend: function() { console.log('prepend'); }, method1: function() { console.log('running method 1'); }, method2: function() { console.log('running method 2'); }, method3: function() { console.log('running method 3'); } }; decorate(objectA, objectA.methodPrepend); objectA.method1(); // prepend\n running method 1 objectA.method2(); // prepend\n running method 2 objectA.method3(); // prepend\n running method 3
There is a lot more that can be done with this, for example having support for an asynchronous function to decorate, but those are just modifications on this strategy.
Github Location: https://github.com/Jacob-Friesen/obscurejs/blob/master/2014/decorator.js
Decorator Pattern
You can add functionality to the processing classes by extending them. For example, let's say I want to have a PVector that represents a point in space that has a velocity vector and bounces around (you know, that classic bouncing balls kind of thing). instead of making a Ball object or something that has two PVector objects, one for position and one for veloctiy, I can make a class extending PVector and just add the functionality I want like....
public class Vec extends PVector { public PVector v; public void flipIfPastEdge() { if(x < 0 || x > width) { v.set(v.x * -1, v.y, 0); } if(y < 0 || y > height) { v.set(v.x, v.y * -1, 0); } } public void updatePosition() { x += v.x; y += v.y; } public Vec(float x, float y) { super(x, y); } }
The advantage of using this "decorator pattern" approach is that you can declare objects of type PVector and make them instances of your new subclass. Like.... PVector p = new Vec(100, 200); And these instances of your new subclass can be used in any functions that expect PVector objects. Plus, you get all the functions available in PVector by inheritance. Just a thought. oh p.s. I'm assuming you'd be declaring this in the processing IDE, so that it's a nested class and you have width and height available. If you're doing a truly separate class in eclipse or something you'd have to pass in the PApplet to the constructor or have a setter or something.

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Advanced delegation. A decorator design pattern example.
The motivation =========== You probably wrote the following lines in your view controllers plenty of times: self.tableView.delegate = self; self.tableView.dataSource = self; *Usually*, that's fine. However, if you have another table view in your app which has more or less the same look and feel, but a different controller managing it, a problem rises. It would be nice to reuse all the delegation code you wrote in your initial controller. And only change the data and do other small customisations. You could tackle this problem in several ways. But before we start, know that you can find the Github project for this article [here](https://github.com/valentinradu/UITableView-Decorator-Example). The inheritance solution ================= So, one way would be to have a generic view controller, make it the superclass of both of your controllers and implement the delegation methods in it. Than would solve the initial problem, however if for example the two table views have a different header and footer and you override `tableView:viewForHeaderInSection:` and `tableView:viewForFooterInSection:` a third table view that would like to have the footer from the first and the header from the second would have no way to get it without duplicating code. [^1] The aggregation solution ================== Another way to do it would be to create and use some delegate objects instead of passing `self` as a delegate. dataSourceObject = [[VRDataSource alloc] init]; delegateObject = [[VRDelegate alloc] init]; self.tableView.dataSource = dataSourceObject; self.tableView.delegate = delegateObject; The objects are of a different class, so multiple table views can use different instances of it. That sounds nice, the delegates can even have their own inheritance structure, which means no code will ever be duplicated, which is even greater. However, our objects don't have direct access to the controller's properties and methods, which means there will be one handling method on the delegate side and one on the controller side: - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { //the controller is our resolver in this case [self.resolver didSelectRowAtIndexPath:indexPath]; } Also, this means we will need a generic controller to respond to those messages, or a protocol which has to be implemented by all the controllers wishing to delegate responsibilities to our objects. The decorator solution ================ A nice way to solve all the problems above and also have the freedom to implement parts of your delegates in different classes is by using the [decorator design pattern](http://en.wikipedia.org/wiki/Decorator_pattern). [^2] So, we want the delegates to be different objects, but still be able to message **transparently** our controller. They sound like proxies to me [^3]. So, we first init our delegate objects keeping a reference to our decorated object, which in our case is the controller. - (id)initWithDecoratedObject:(id) decObj { self = [super init]; if (self) { self.decoratedObject = decObj; } return self; } Then, every message we receive in our decorators (delegates) and we can't respond to, we forward towards our decorated object (controller). Each method override is explained in the code below. //the first thing the forwarding mechanism does //is calling this method if there is no selector //found //we override it and try to send the same message to our //decorated method //if that fails too, we have nothing better to do than let //the system rise the exception by returning self - (id)forwardingTargetForSelector:(SEL)aSelector { if ([_decoratedObject respondsToSelector:aSelector]) { return _decoratedObject; } return self; } //objective-c is smart enough to know the //difference between inheritence and this 'fake //inheritence' we're trying to do //methods like respondsToSelector: and isKindOfClass: look only //at the inheritance hierarchy, never at the forwarding chain //so we force them to consider it by overriding them - (BOOL)respondsToSelector:(SEL)aSelector { if ( [super respondsToSelector:aSelector] ) return YES; else { if ([_decoratedObject respondsToSelector:aSelector]) { return YES; } } return NO; } - (BOOL)isKindOfClass:(Class)aClass { if ([super isKindOfClass:aClass]) { return YES; } else { if ([_decoratedObject isKindOfClass:aClass]) { return YES; } } return NO; } This way, we will be able to implement some of the methods in our designated delegates and some in our view controller. Which saves us the trouble of forwarding the messages ourselves manually, like in the aggregate solution. Another nice thing about this technique is that you can add or remove a delegate method from your delegate at runtime, which makes it very easy to customise. Also, a nice chain of delegates objects can be formed to give you extra control on how our table view looks. To better visualise all this, here is the set up code: //init the controller //this is just a basic UIViewController subclass implementing //DEDecoratedViewControllerProtocol protocol //a nice thing about this method is that you can keep //your model-controller relation intact //so, even if the controler will not be the table view delegate, //it will still hold the model data for us DERootViewController * viewController = [[DERootViewController alloc] init]; //our model data is simply a dictionary for the sake of simplicity viewController.tableItems = @[@{@"title": @"Africa"}, @{@"title": @"America"}, @{@"title": @"Asia"}, @{@"title": @"Europe"}]; //decorate the text label with a color dec = [[DERedDecorator alloc] initWithDecoratedObject:viewController]; //is as easy as this to change it to another color //DEAbstractDecorator * dec = //[[DEGrayDecorator alloc] initWithDecoratedObject:viewController]; //then decorate the table view with a footer //notice that we pass the prev decoration as parameter //this is really nice because we can have a chain of decorations on //the same decorated object dec = [[DEFooterDecorator alloc] initWithDecoratedObject:dec]; //maybe we want a header too dec = [[DEHeaderDecorator alloc] initWithDecoratedObject:dec]; //create the tableview UITableView * tableView = [[UITableView alloc] initWithFrame:self.window.frame style:UITableViewStylePlain]; //delegate to decorator tableView.delegate = dec; tableView.dataSource = dec; For a better overview on how all this works [here](https://github.com/valentinradu/UITableView-Decorator-Example) is a Github project with all the code within a working example. [^1]:I know, that's unlikely to happen, probably not the best example, but bear with me, the implications of the decorator pattern lay beyond this type of delegation. [^2]:Is not a pure implementation, but it's pretty close. [^3]:When it comes to implementation, I choose not to use `NSProxy` because [Apple's Documentation](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html) states that `forwardInvocation:` is much more expensive than `forwardingTargetForSelector:` which is not implemented for NSProxy.
DP/10/24/SP: Decorator pattern
Idea is: The Decorator pattern provides us with a way to modify the behavior of individual objects without having to create a new derived class.
Attach additional responsibilities to an object dynamically.
Decorators provide a flexible alternative to subclassing for extending functionally
Also known as Wrapper
A flexible approach is to enclose the component in another object. The enclosing object is called a decorator.
The decorator conforms forwards requests to the component and may perform additional actions before or after forwarding. Transparency lets you nest decorators recursively, thereby allowing an unlimited number of added responsibilities.
Java Design Patterns - Decorator Pattern (Part 2)
Second part of Design Patterns review is about Decorator Pattern. If you miss the first part you can check out the Strategy Pattern. It's the night right now and I am looking up into Decorating Coffee. For the before post I got a custom idea using Kuroko no Basket("a popular manga on shounen jump"). But for this review I am using the same HeadFirst example cutting off the details to the minimum.
Decorator Pattern allows us to wrap objects around each other to add additional functionalities in runtime. If you have used BufferedReader you'll probably remember passing a FileReader object to the BufferedReader constructor. That's the same decorator pattern and it's quite useful.
We going to have Black Coffee with Mocha("Infact double the Mocha")… So let's build this Coffee Machine.
First design wise we going to use abstract class to represent a Beverage.
public abstract class Beverage {
String description;
public abstract double cost();
public String getDescription(){
return description;
}
}
Then we are going to build up our Black Coffee class. We are calculating the price of the black coffee inside it's overridden cost() method. The Description is later used to generate the name of the drink.
public class BlackCoffee extends Beverage {
public BlackCoffee() {
description = "Black Coffee";
}
@Override
public double cost() {
return 100;
}
}
Then we are building a CondimentDecorator abstract class that provides an abstract getDescription() method.
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
Then we are defining another abstract class for Condiments such as Mocha.
public abstract class Condiments extends Beverage{
}
Here we have the Mocha class...
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription()+" Mocha";
}
@Override
public double cost() {
return beverage.cost() + 60;
}
}
Take a look at this class closely since magic happens here. We are setting up the beverage object using the overloaded constructor and then using an overridden cost() method to add the cost of the beverage and the cost of the current condiment. This can be repeated in any rounds as possible since Mocha is also a subclass of Beverage indirectly.
Let's wipe up some Hot Coffee...
public void testBlackCoffee() {
BlackCoffee blackCoffee = new BlackCoffee();
Mocha mocha = new Mocha(blackCoffee);
Mocha mocha2 = new Mocha(mocha);
System.out.println("Now Serving "+mocha2.getDescription()+" cost :"+mocha2.cost());
}
And the results comes out as
Now Serving Black Coffee Mocha Mocha cost :220.0
Decorator pattern comes handy in many business logics since we can use it to cover a paying cycle such as Estimate ->Job -> Invoice cycle. So don't forget it!