7.太多-享元模式(Flyweight)+装饰模式(Decorator)
今天终于完成了所有科目的考试,心情没有想象中的那么高兴,只是考完而已,呵呵,哎,为什么呢,好像觉得自己越来越接近社会了,我突然好怀念大学,每天的上班下班让人觉得很烦恼似乎,我还记得很久以前,我很憧憬自己长大,然后成为很厉害的人,那时对于我来说最大的困难就是不能很快的长大,长大后什么问题都不是问题了,呵呵,我是一个很固执的人,很多东西我都很追求完美不愿放弃一点,但是社会的现实始终让我暂时低下了头,但是我知道我没有明白,我永远都不会明白,我就是没有达到目的不会放弃的人,就算一年,10年,一百年,我愿意付出这个代价,也许不值得,现在没有实现,是因为你还不够强大,所以你不能要求更多.
编程就是生活,算法也是生活,程序员也有喜怒哀乐,我愿意把它放到我的模式中展现出来。
享元模式(Flyweight):
刚开始对于这个新名词,一下子被他吓到了,我好想随便看看,然后就这样算了,当做是敷衍自己,但是我对自己又说,那你比不看还要糟糕,的确,在我前3年的时间中,我试过太多这样的事情了,面对困难,只是了解,从不敢深入探讨,只在乎和他人吹水,骗骗自己骗骗别人,告诉自己,这样的日子是尽头了,不真正弄懂,不罢休。
其实享元模式的基本实现是将可以复杂对象中不变的东西提取出来,作为静态,其他变得就传进去,这样就能将几百万的对象一下子就变成几个
内蕴状态:就是不变的部分
外蕴状态:就是变得部分咯
举一个非常简单的例子:一个咖啡摊的例子,在这个咖啡摊(Coffee Stall)所使用的系统里,有一系列的咖啡"风味(Flavor)"。客人到摊位上购买咖啡,所有的咖啡均放在台子上,客人自己拿到咖啡后就离开摊位。咖啡有内蕴状态,也就是咖啡的风味;咖啡没有环境因素,也就是说没有外蕴状态。如果系统为每一杯咖啡都创建一个独立的对象的话,那么就需要创建出很多的细小对象来。这样就不如把咖啡按照种类(即"风味")划分,每一种风味的咖啡只创建一个对象,并实行共享。
使用咖啡摊主的语言来讲,所有的咖啡都可按"风味"划分成如Capucino、Espresso等,每一种风味的咖啡不论卖出多少杯,都是全同、不可分辨的。所谓共享,就是咖啡风味的共享,制造方法的共享等。因此,享元模式对咖啡摊来说,就意味着不需要为每一份单独调制。摊主可以在需要时,一次性地调制出足够一天出售的某一种风味的咖啡。
很显然,这里适合使用单纯享元模式。
咖啡屋的例子
在前面的咖啡摊项目里,由于没有供客人坐的桌子,所有的咖啡均没有环境的影响。换言之,咖啡仅有内蕴状态,也就是咖啡的种类,而没有外蕴状态。
下面考虑一个规模稍稍大一点的咖啡屋(Coffee Shop)项目。屋子里有很多的桌子供客人坐,系统除了需要提供咖啡的"风味"之外,还需要跟踪咖啡被送到哪一个桌位上,因此,咖啡就有了桌子作为外蕴状态。
由于外蕴状态的存在,没有外蕴状态的单纯享元模式不再符合要求。系统的设计可以利用有外蕴状态的单纯享元模式。
例子略
装饰模式(Decorator):
刚才享元模式解决的问题是太多对象了,那么现在装饰模式解决的是什么呢,就是太多类,Decorator 模式是指:用分层的对象(layered objects)动态地和透明地给单个对象添加功能(responsibilities)。其实书上的例子写的很好,我直接放上来吧,也很容易理解,不过关于如何实践,这还是需要一番理解。
一个关于咖啡的例子 考虑去当地的一家咖啡馆BeanMeUp 喝杯咖啡。那里通常会提供许多种不同的饮 料——蒸馏咖啡, lattes, 茶, 冰咖啡,热巧克力饮品,而且还有许多额外的添加 物,比如生奶油或者额外的蒸馏咖啡粉末(当然这些是要另外收钱的)。你也可以不 支付额外的费用而改变你的饮料,比如你可以要求把普通咖啡换成脱咖啡因咖啡。 有一点是非常清楚的,如果我们想给上面所有这些饮料和它们的组合建模,那将 会产生一张非常大的类图。为了能够清楚的说明问题,我们只考虑所有咖啡品种的一 个子集:Espresso, Espresso Con Panna, Café Late, Cappuccino and Café Mocha. 我们提供2 种额外的添加物——生奶油(“whipped”)和蒸馏咖啡粉,和三种可选择 的饮品——脱咖啡因咖啡,steamed milk ("wet") 和 foamed milk ("dry"). 每种组合对应一个类 一个解决办法是给每种组合都创建一个类。用它来描述每种饮料(的组成)和价 格等等。最终产生的饮料单是巨大的。你可以看到,创建你想要的组合是非常简单的,因为你只要创建某个类的一个实例就可以了。但是,这种方法存在许多问题。首先,这些组合都是静态固定死的,客户想要的每个组合都必须预先创建好。其次,整个组合生成的菜单实在是太大了,要找到某个特定的组合非常困难而且耗时。
Decorator 方法 另外可以采用把这些饮料拆成类似于esspresso 和foamed milk 的组件 (components),然后让顾客通过组合这些组件来描述某种特定的咖啡饮料。 我们使用Decorator 模式,通过编程来实现上述想法。Decorator 通过包裹 (wrapping)一个组件来给它增加功能,但是Decorator 兼容它所包裹的那个类的接 口,这样,对component 的包裹就是透明的。Decorator 自身又可以被(别的 Decorator)包裹而不丧失其透明性。
其实为你的对象添加一些衣服鞋子这样,代码太长了,不写了,没心情今天,
折衷(Compromise) 用上面这种方法来描述某种咖啡饮品实在是太冗长了。对于那些经常会被用到的 组合,如果用一种更快的方法来描述它们会方便很多。 这里的第三种方法就是前面两种方法的组合,也就是灵活性和易用性相结合。这 种折衷是通过创建合适大小的供常规选择的菜单来实现的,这个菜单基本上是不怎么 太多(Too many) 变化的,但是如果你想给这些基本饮品加点伴侣(比如whipped cream, decaf 等), 那你可以用decorators 来改变基本饮品。这其实也是大多数咖啡馆提供的那种菜单。