Q:何为装饰模式?shell
()地给一个对象添加一些额外的(),而且()时,并不影响原对象。扩展功能来讲,装饰器模式相比生成子类更为灵活。swift
Q:使用场景?app
1.想要在不影响其余对象的状况下,以__、__的方式给单个对象添加职责。 2.想要()一个类的行为,却作不到。类定义可能被隐藏,没法进行子类化;或者,对类的每一个行为的扩展,为支持每种功能组合,将产生大量的子类。 3.对类的()的扩展是可选的。框架
Q:主要角色?ide
4个核心角色 角色一:()组件 角色二:()组件 角色三:()者 角色四:()者atom
Q:CocoaTouch中的装饰模式实现方式?.net
动态地给一个对象添加一些额外的职责,而且去除时,并不影响原对象。扩展功能来讲,装饰器模式相比生成子类更为灵活。代理
1.想要在不影响其余对象的状况下,以动态、透明的方式给单个对象添加职责。 2.想要扩展一个类的行为,却作不到。类定义可能被隐藏,没法进行子类化;或者,对类的每一个行为的扩展,为支持每种功能组合,将产生大量的子类。 3.对类的职责的扩展是可选的。code
“外表变动”(装饰) | “内部变动”(策略) |
---|---|
从外部变动 | 从内部变动 |
每一个节点不知道变动 | 每一个节点知道一组预约义的变动方式 |
4个核心角色 角色一:抽象组件 角色二:具体组件 角色三:抽象装饰者 角色四:具体装饰者component
Decorator 案例:手机壳---iPhoneX->9688 角色一:抽象组件->MobilePhone(手机) 角色二:具体组件->iPhoneX 角色三:抽象装饰者->MobilePhoneShell 角色四:具体装饰者(具体扩展功能)-> 质量好的手机壳:耐磨、防水、防尘…(300) 耐磨:wearproof() 防水:waterproof() 防尘:dustproof() expensive() GoodShell
质量差的手机壳:耐磨(50) 便宜:cheap() PoorShell
//抽象组件->手机 protocol MobilePhone { func shell() } //具体组件->iPhoneX class IPhoneX: MobilePhone { func shell() { print("iPhoneX") } } //具体组件->6S class IPhone6S: MobilePhone { func shell() { print("iPhone6S") } } //抽象装饰者 跟代理同样 //特色一:继承(实现)抽象组件 //特色二:持有抽象组件引用 class MobilePhoneShell: MobilePhone { private var mobile:MobilePhone init(mobile:MobilePhone) { self.mobile = mobile } func shell() { self.mobile.shell() } } //具体装饰者->好的手机壳 class GoodShell: MobilePhoneShell { override init(mobile: MobilePhone) { super.init(mobile: mobile) } func wearproof(){ print("贵--耐磨功能") } func waterproof(){ print("贵--防水功能") } func dustproof(){ print("贵--防尘功能"); } } //具体装饰者->好的手机壳 class PoorShell: MobilePhoneShell { override init(mobile: MobilePhone) { super.init(mobile: mobile) } func wearproof(){ print("便宜--耐磨功能") } func cheap(){ print("便宜") } }
[@protocol](https://my.oschina.net/u/819710) ImageComponent <NSObject> // We will intercept these // UIImage methods and add // additional behavior //截获UIImage的方法,插入附加行为 @optional - (void) drawAsPatternInRect:(CGRect)rect; - (void) drawAtPoint:(CGPoint)point; - (void) drawAtPoint:(CGPoint)point blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; - (void) drawInRect:(CGRect)rect; - (void) drawInRect:(CGRect)rect blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; [@end](https://my.oschina.net/u/567204)
#import "ImageComponent.h" [@interface](https://my.oschina.net/u/996807) UIImage (ImageComponent) <ImageComponent> [@end](https://my.oschina.net/u/567204) #import "UIImage+ImageComponent.h" //@implementation UIImage (ImageComponent) // //@end
#import "ImageComponent.h" #import "UIImage+ImageComponent.h" //核心装饰器类 @interface ImageFilter : NSObject <ImageComponent> { @private id <ImageComponent> component_;//这个引用会被其余具体装饰器装饰 } @property (nonatomic, retain) id <ImageComponent> component; - (void) apply; - (id) initWithImageComponent:(id <ImageComponent>) component; - (id) forwardingTargetForSelector:(SEL)aSelector;//重载 /* // overridden methods in UIImage APIs - (void) drawAsPatternInRect:(CGRect)rect; - (void) drawAtPoint:(CGPoint)point; - (void) drawAtPoint:(CGPoint)point blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; - (void) drawInRect:(CGRect)rect; - (void) drawInRect:(CGRect)rect blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha; */ @end #import "ImageFilter.h" @implementation ImageFilter @synthesize component=component_; - (id) initWithImageComponent:(id <ImageComponent>) component { if (self = [super init]) { // save an ImageComponent [self setComponent:component]; } return self; } - (void) apply { // should be overridden by subclasses // to apply real filters //应该由子类重载,应用真正的滤镜 } - (id) forwardingTargetForSelector:(SEL)aSelector { NSString *selectorName = NSStringFromSelector(aSelector); if ([selectorName hasPrefix:@"draw"]) { [self apply]; } return component_; } /* - (void) drawAsPatternInRect:(CGRect)rect { [self apply]; [component_ drawAsPatternInRect:rect]; } - (void) drawAtPoint:(CGPoint)point { [self apply]; [component_ drawAtPoint:point]; } - (void) drawAtPoint:(CGPoint)point blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha { [self apply]; [component_ drawAtPoint:point blendMode:blendMode alpha:alpha]; } - (void) drawInRect:(CGRect)rect { [self apply]; [component_ drawInRect:rect]; } - (void) drawInRect:(CGRect)rect blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha { [self apply]; [component_ drawInRect:rect blendMode:blendMode alpha:alpha]; } */ @end
装饰类:旋转+阴影
#import "ImageFilter.h" @interface ImageTransformFilter : ImageFilter { @private CGAffineTransform transform_; CGSize size_; } @property (nonatomic, assign) CGAffineTransform transform; @property (nonatomic, assign) CGSize size; - (id) initWithImageComponent:(id <ImageComponent>)component transform:(CGAffineTransform)transform size:(CGSize )size; - (void) apply; @end #import "ImageTransformFilter.h" @implementation ImageTransformFilter @synthesize transform = transform_; @synthesize size = size_; - (id) initWithImageComponent:(id <ImageComponent>)component transform:(CGAffineTransform)transform size:(CGSize )size { if (self = [super initWithImageComponent:component]) { [self setTransform:transform]; size_ = size; } return self; } - (void) apply { // CGSize size = size_; // if (NULL != UIGraphicsBeginImageContextWithOptions) // UIGraphicsBeginImageContextWithOptions(size, NO, 0); // else // UIGraphicsBeginImageContext(size); // CGContextRef context = UIGraphicsGetCurrentContext(); // setup transformation CGContextConcatCTM(context, transform_); } @end #import "ImageFilter.h" @interface ImageShadowFilter : ImageFilter - (void) apply; @end @implementation ImageShadowFilter - (void) apply { CGContextRef context = UIGraphicsGetCurrentContext(); // set up shadow CGSize offset = CGSizeMake (-25, 15); CGContextSetShadow(context, offset, 20.0); } @end
@interface UIImage (BaseFilter) - (CGContextRef) beginContext; - (UIImage *) getImageFromCurrentImageContext; - (void) endContext; @end #import "UIImage+BaseFilter.h" @implementation UIImage (BaseFilter) - (CGContextRef) beginContext { // Create a graphics context with the target size // On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions // to take the scale into consideration // On iOS prior to 4, fall back to use UIGraphicsBeginImageContext CGSize size = [self size]; if (NULL != UIGraphicsBeginImageContextWithOptions) UIGraphicsBeginImageContextWithOptions(size, NO, 0); else UIGraphicsBeginImageContext(size); CGContextRef context = UIGraphicsGetCurrentContext(); return context; } - (UIImage *) getImageFromCurrentImageContext { [self drawAtPoint:CGPointZero]; // Retrieve the UIImage from the current context UIImage *imageOut = UIGraphicsGetImageFromCurrentImageContext(); return imageOut; } - (void) endContext { UIGraphicsEndImageContext(); } @end @interface UIImage (Transform) - (UIImage *) imageWithTransform:(CGAffineTransform)transform; @end @implementation UIImage (Transform) - (UIImage *) imageWithTransform:(CGAffineTransform)transform { CGContextRef context = [self beginContext]; // setup transformation CGContextConcatCTM(context, transform); // Draw the original image to the context UIImage *imageOut = [self getImageFromCurrentImageContext]; [self endContext]; return imageOut; } @end @interface UIImage (Shadow) - (UIImage *) imageWithDropShadow; @end #import "UIImage+BaseFilter.h" @implementation UIImage (Shadow) - (UIImage *) imageWithDropShadow { CGContextRef context = [self beginContext]; // set up shadow CGSize offset = CGSizeMake (-25, 15); CGContextSetShadow(context, offset, 20.0); // Draw the original image to the context UIImage * imageOut = [self getImageFromCurrentImageContext]; [self endContext]; return imageOut; } @end
#import "ViewController.h" #import "ImageTransformFilter.h" #import "ImageShadowFilter.h" #import "DecoratorView.h" #import "UIImage+Transform.h" #import "UIImage+Shadow.h" @interface ViewController () @property (strong, nonatomic) IBOutlet UIImageView *OriginalPic; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; CGAffineTransform rotateTransform = CGAffineTransformMakeRotation(-M_PI / 4); /*关于M_PI #define M_PI 3.14159265358979323846264338327950288 进行旋转 通常咱们理解的旋转为:0-360(度) CGAffineTransformMakeRotation方法,使用的是M_PI的方式。 转化公式:0-360=0-2M_PI M_PI = 180 CGAffineTransformMakeRotation(M_PI * -0.5); 也就是旋转-90度 */ CGAffineTransform translateTransform = CGAffineTransformMakeTranslation (-self.OriginalPic.image.size.width/6 ,self.OriginalPic.image.size.height/2); CGAffineTransform finalTransform = CGAffineTransformConcat(rotateTransform, translateTransform); // a true subclass approach id <ImageComponent> transformedImage = [[ImageTransformFilter alloc] initWithImageComponent:self.OriginalPic.image transform:finalTransform size:(self.OriginalPic.frame.size)]; id <ImageComponent> finalImage = [[ImageShadowFilter alloc] initWithImageComponent:transformedImage]; [self CategoriesMethod:finalTransform]; } -(void)CategoriesMethod:(CGAffineTransform)finalTransform{ // a category approach // add transformation UIImage *transformedImage = [self.OriginalPic.image imageWithTransform:finalTransform]; // add shadow // id <ImageComponent> finalImage = [transformedImage imageWithDropShadow]; UIImage * finalImage = [transformedImage imageWithDropShadow]; // category approach in one line // id <ImageComponent> finalImage = [[image imageWithTransform:finalTransform] imageWithDropShadow]; DecoratorView *decoratorView = [[DecoratorView alloc] initWithFrame:CGRectMake(67, 359, 255, 264)];//y 20 y 359 [decoratorView setImage:finalImage]; // [self.FilterPic setImage:finalImage]; [self.view addSubview:decoratorView]; } @end @interface DecoratorView : UIView { @private UIImage *image_; } @property (nonatomic, retain) UIImage *image; @end #import "DecoratorView.h" @implementation DecoratorView @synthesize image=image_; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code. [self setBackgroundColor:[UIColor clearColor]]; } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code. [image_ drawInRect:rect]; } //- (void)dealloc { // [super dealloc]; //} /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // Drawing code } */ @end