装饰者模式

装饰者模式

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
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息