详解iOS App设计模式开发中对于享元模式的运用

享元模式的概念

在面向对象软件设计中,利用公共对象不仅能节省资源还能提高性能。共享的对象只能提供某些内在的信息,而不能用来识别对象。专门用于设计可共享对象的一种设计模式叫做享元模式(Flyweight pattern)。

实现享元模式需要两个关键组件,通常是可共享的享元对象和保存他们的池。某种中央对象维护这个池,并从它返回适当的实例。
运用共享技术有效地支持大量细粒度的对象。

公共交通(如公共汽车)已有一百多年的历史了。大量去往相同方向的乘客可以分担保有和经营车辆(如公共汽车)的费用。公共汽车有多个站台,乘客沿着路线在接近他们目的地的地方上下车。到达目的地的费用仅与行程有关。跟保有车辆相比,乘坐公共汽车要便宜得多。这就是利用公共资源的好处。

在面向对象软件设计中,我们利用公共对象不仅能节省资源还能提高性能。比方说,某个人物需要一个类的一百万个实例,但我们可以把这个类的一个实例让大家共享,而把某些独特的信息放在外部,节省的资源可能相当可观(一个实例与一百万个实例的差别)。共享的对象只提供某些内在的信息,而不能用来识别对象。专门用于设计可共享对象的一种设计模式叫做享元模式。

使得享元对象是轻量级的最重要原因是什么呢?不是它们的大小,而是通过共享能够节省的空间总量。某些对象的独特状态可以拿到外部,在别处管理,其余部分被共享。比如说,原来需要一个类的一百万个对象,但因为这个类的对象为享元,现在只要一个就够了。这就是由于可共享的享元对象让整个系统变得轻量的原因。通过仔细的设计,内存的节省非常可观。在iOS开发中,节省内存意味着提升整体性能。


享元模式的实例应用

我们创建一个WebSiteFactory工厂类,来维护池中的享元对象,根据父类型返回各种类型的具体享元对象,代码如下:

代码如下:

#import <Foundation/Foundation.h>
#import "WebSiteProtocol.h"
@interface WebSiteFactory : NSObject
 
@property (nonatomic, strong) NSDictionary *flyweights; //共享对象
 
- (id<WebSiteProtocol>)getWebSiteCategory:(NSString *)webKey;
- (NSInteger)getWebSiteCount;
 
@end

代码如下:

#import "WebSiteFactory.h"
#import "ConcreteWebSite.h"
@implementation WebSiteFactory
 
- (instancetype)init {
    self = [super init];
    if (self) {
        _flyweights = [NSDictionary dictionary];
    }
    return self;
}
 
- (id<WebSiteProtocol>)getWebSiteCategory:(NSString *)webKey {   
    __block id<WebSiteProtocol> webset = nil;
    [self.flyweights enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        if (webKey == key) {
            webset = obj;
            *stop = YES;
        }
    }];
    
    if (webset == nil) {
        ConcreteWebSite *concreteWebset = [[ConcreteWebSite alloc] init];
        concreteWebset.webName = webKey;
        webset = concreteWebset;
        
        NSMutableDictionary *mutabledic = [NSMutableDictionary dictionaryWithDictionary:self.flyweights];
        [mutabledic setObject:webset forKey:webKey];
        self.flyweights = [NSDictionary dictionaryWithDictionary:mutabledic];
    }
    
    return webset;
}
 
- (NSInteger)getWebSiteCount {
    return self.flyweights.count;
}
 
@end

代码中的getWebSiteCategory方法可以返回具体的享元对象,返回的这个享元对象同时遵守WebSiteProtocol的协议,WebSiteProtocol的代码如下:

代码如下:

#import <Foundation/Foundation.h>
#import "User.h"
@protocol WebSiteProtocol <NSObject>
 
- (void)use:(User *)user;
 
@end

ConcreteWebSite的代码如下:

代码如下:

#import <Foundation/Foundation.h>
#import "WebSiteProtocol.h"
@interface ConcreteWebSite : NSObject <WebSiteProtocol>
 
@property (nonatomic, copy) NSString *webName;
 
@end

代码如下:

#import "ConcreteWebSite.h"
 
@implementation ConcreteWebSite
 
- (void)use:(User *)user {
    NSLog(@"网站分类:%@ 用户名字:%@", self.webName, user.userName);
}
 
@end

User的代码如下:

代码如下:

#import <Foundation/Foundation.h>
 
@interface User : NSObject
 
@property (nonatomic, copy) NSString *userName;
 
@end

代码如下:

#import "User.h"
 
@implementation User
 
@end

至此,享元模式的代码已经完成了,我们来看下在客户端怎么使用享元模式,代码如下:

代码如下:

#import "ViewController.h"
#import "WebSiteProtocol.h"
#import "WebSiteFactory.h"
#import "ConcreteWebSite.h"
#import "User.h"
typedef id<WebSiteProtocol> WebsiteType;
@interface ViewController ()
 
@end

代码如下:

@implementation ViewController
 
- (void)viewDidLoad {
    [super viewDidLoad];
    // 通过工厂方法返回各种具体享元对象,维护池中的享元对象
    WebSiteFactory *factory = [[WebSiteFactory alloc] init];
    
    // 返回具体的享元对象
    WebsiteType type1 = [factory getWebSiteCategory:@"首页"];
    User *user1 = [[User alloc] init];
    user1.userName = @"张三";
    // 享元对象都具有use方法
    [type1 use:user1];
    
    WebsiteType type2 = [factory getWebSiteCategory:@"商店"];
    User *user2 = [[User alloc] init];
    user2.userName = @"李四";
    [type2 use:user2];
    
    WebsiteType type3 = [factory getWebSiteCategory:@"案例"];
    User *user3 = [[User alloc] init];
    user3.userName = @"王五";
    [type3 use:user3];
    
    NSInteger count = [factory getWebSiteCount];
    NSLog(@"个数: %ld", (long)count);
    
}
 
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
 
@end

输出如下:

2015-09-12 15:59:55.322 FlyweightPattern[42020:1723017] 网站分类:首页 用户名字:张三
2015-09-12 15:59:55.322 FlyweightPattern[42020:1723017] 网站分类:商店 用户名字:李四
2015-09-12 15:59:55.322 FlyweightPattern[42020:1723017] 网站分类:案例 用户名字:王五
2015-09-12 15:59:55.323 FlyweightPattern[42020:1723017] 个数: 3

分享相同的资源以执行任务,可能比使用个人的资源完成同样的事情更加高效。享元模式可以通过共享一部分必需的对象,来节省大量的内存。
   
何时使用享元模式
(1)应用程序使用很多对象;
(2)在内存中保存对象会影响内存性能;
(3)对象的多数特有状态(外在状态)可以放到外部而轻量化;
(3)移除了外在状态后,可以用较少的共享对象替代原来的那组对象;
(4)应用程序不依赖于对象标示,因为共享对象不能提供唯一的标示。

(0)

相关推荐

  • 详解Java设计模式编程中的Flyweight享元模式的开发结构

    享元(Flyweight)模式:通过共享技术以便有效的支持大量细粒度的对象. 享元模式在阎宏的<java与模式>中分为单纯享元模式和复合享元模式,复合模式的复合享元是不可以共享的,享元对象能做到共享的关键是区分内蕴态(Internal State)和外蕴态( External State).这两个"蕴态"翻译的太难懂,我不是说翻译的不好,可能是我理解能力差,还是<Design Pattern Elements of Reusable Object-Oriented S

  • 轻松掌握JavaScript享元模式

    在JavaScript中,浏览器特别是移动端的浏览器分配的内存很有限,如何节省内存就成了一件非常有意义的事情.节省内存的一个有效方法是减少对象的数量. 享元模式(Flyweight),运行共享技术有效地支持大量细粒度的对象,避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). 享元模式可以避免大量非常相似类的开销,在程序设计中,有时需要生产大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数以外,开销基本相同的话,就可以大幅度较少需要实例化的类的数量.如果能把那些参

  • Java设计模式之共享模式/享元模式(Flyweight模式)介绍

    Flyweight定义:避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). 为什么使用共享模式/享元模式 面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞大,比如,字处理软件,如果以每个文字都作为一个对象,几千个字,对象数就是几千,无疑耗费内存,那么我们还是要"求同存异",找出这些对象群的共同点,设计一个元类,封装可以被共享的类,另外,还有一些特性是取决于应用(context),是不可共享的,这也Flyweight中两个重要概念内

  • 轻松掌握Java享元模式

    定义:它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件. 特点:大大减少对象的创建,降低系统的内存,使效率提高. 企业级开发及常用框架中的应用:数据库的连接池,String的常量缓存池 具体代码实例: import java.util.HashMap; import java.util.Map; import java.util.Random; public class Demo { public stati

  • JS实现简单的图书馆享元模式实例

    本文实例讲述了JS实现简单的图书馆享元模式.分享给大家供大家参考.具体如下: <!DOCTYPE html> <html> <head> <title>享员模式</title> </head> <body> <script> /* *flyweight 享员模式 */ //例子是一个图书馆存书借书 ->_-> var Book = function(id, title, author, genre,

  • 深入理解JavaScript系列(37):设计模式之享元模式详解

    介绍 享元模式(Flyweight),运行共享技术有效地支持大量细粒度的对象,避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). 享元模式可以避免大量非常相似类的开销,在程序设计中,有时需要生产大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数以外,开销基本相同的 话,就可以大幅度较少需要实例化的类的数量.如果能把那些参数移动到类实例的外面,在方法调用的时候将他们传递进来,就可以通过共享大幅度第减少单个实例 的数目. 那么如果在JavaScript中应用享元模式

  • php设计模式 FlyWeight (享元模式)

    享元模式英文称为"Flyweight Pattern",我非常感谢将Flyweight Pattern翻译成享元模式的那位强人,因为这个词将这个模式使用的方式明白得表示了出来:如果翻译成为羽量级模式或者蝇量级模式等等,虽然可以含蓄的表现出使用此模式达到的目的,但是还是没有抓住此模式的关键. 享元模式的定义为:采用一个共享来避免大量拥有相同内容对象的开销.这种开销中最常见.直观的就是内存的损耗.享元模式以共享的方式高效的支持大量的细粒度对象. 在名字和定义中都体现出了共享这一个核心概念,

  • 学习JavaScript设计模式之享元模式

    一.定义 享元(flyweight)模式是一种用于性能优化的模式,核心是运用共享技术来有效支持大量细刻度的对象. 在JavaScript中,浏览器特别是移动端的浏览器分配的内存并不算多,如何节省内存就成了一个非常有意义的事情. 享元模式是一种用时间换空间的优化模式 内衣工厂有100种男士内衣.100中女士内衣,要求给每种内衣拍照.如果不使用享元模式则需要200个塑料模特:使用享元模式,只需要男女各1个模特. 二.什么场景下使用享元模式? (1)程序中使用大量的相似对象,造成很大的内存开销 (2)

  • C++设计模式编程之Flyweight享元模式结构详解

    由遇到的问题引出享元模式: 在面向对象系统的设计何实现中,创建对象是最为常见的操作.这里面就有一个问题:如果一个应用程序使用了太多的对象,就会造成很大的存储开销.特别是对于大量轻量级(细粒度)的对象,比如在文档编辑器的设计过程中,我们如果为没有字母创建一个对象的话,系统可能会因为大量的对象而造成存储开销的浪费.例如一个字母"a"在文档中出现了100000 次,而实际上我们可以让这一万个字母"a"共享一个对象,当然因为在不同的位置可能字母"a"有不

  • 总结JavaScript设计模式编程中的享元模式使用

    享元模式不同于一般的设计模式,它主要用来优化程序的性能,它最适合解决大量类似的对象而产生的性能问题.享元模式通过分析应用程序的对象,将其解析为内在数据和外在数据,减少对象的数量,从而提高应用程序的性能. 基本知识 享元模式通过共享大量的细粒度的对象,减少对象的数量,从而减少对象的内存,提高应用程序的性能.其基本思想就是分解现有类似对象的组成,将其展开为可以共享的内在数据和不可共享的外在数据,我们称内在数据的对象为享元对象.通常还需要一个工厂类来维护内在数据. 在JS中,享元模式主要有下面几个角色

随机推荐