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