裝飾者模式

裝飾者模式

Q:何爲裝飾模式?shell

()地給一個對象添加一些額外的(),而且()時,並不影響原對象。擴展功能來講,裝飾器模式相比生成子類更爲靈活。swift

Q:使用場景?app

1.想要在不影響其餘對象的狀況下,以__、__的方式給單個對象添加職責。 2.想要()一個類的行爲,卻作不到。類定義可能被隱藏,沒法進行子類化;或者,對類的每一個行爲的擴展,爲支持每種功能組合,將產生大量的子類。 3.對類的()的擴展是可選的。框架

Q:主要角色?ide

4個核心角色 角色一:()組件 角色二:()組件 角色三:()者 角色四:()者atom

Q:CocoaTouch中的裝飾模式實現方式?.net

一、裝飾模式-定義

動態地給一個對象添加一些額外的職責,而且去除時,並不影響原對象。擴展功能來講,裝飾器模式相比生成子類更爲靈活。代理

二、裝飾模式-場景

1.想要在不影響其餘對象的狀況下,以動態、透明的方式給單個對象添加職責。 2.想要擴展一個類的行爲,卻作不到。類定義可能被隱藏,沒法進行子類化;或者,對類的每一個行爲的擴展,爲支持每種功能組合,將產生大量的子類。 3.對類的職責的擴展是可選的。code

3與策略模式的差別

「外表變動」(裝飾) 「內部變動」(策略)
從外部變動 從內部變動
每一個節點不知道變動 每一個節點知道一組預約義的變動方式

四、裝飾模式-角色劃分

4個核心角色 角色一:抽象組件 角色二:具體組件 角色三:抽象裝飾者 角色四:具體裝飾者component

五、裝飾模式-案例分析 swift實現

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("便宜")
	}
}

6.Cocoa Touch框架中使用裝飾模式

6.1子類實現

[@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

6.2分類實現

@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
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息