GoF类图
享元模式
代码实现

interfaceFlyweight{publicfunctionoperation($extrinsicState):void;}classConcreteFlyweightimplementsFlyweight{private$intrinsicState=101;functionoperation($extrinsicState):void{echo'共享享元工具'.($extrinsicState+$this->intrinsicState).PHP_EOL;}}classUnsharedConcreteFlyweightimplementsFlyweight{private$allState=1000;publicfunctionoperation($extrinsicState):void{echo'非共享享元工具:'.($extrinsicState+$this->allState).PHP_EOL;}}
定义共享接口以及它的实现,把稳这里有两个实现,ConcreteFlyweigh进行状态的共享,UnsharedConcreteFlyweight不共享或者说他的状态不须要去共享
classFlyweightFactory{private$flyweights=[];publicfunctiongetFlyweight($key):Flyweight{if(!array_key_exists($key,$this->flyweights)){$this->flyweights[$key]=newConcreteFlyweight();}return$this->flyweights[$key];}}
保存那些须要共享的工具,做为一个工厂来创建须要的共享工具,担保相同的键值下只会有唯一的工具,节省相同工具创建的开销
$factory=newFlyweightFactory();$extrinsicState=100;$flA=$factory->getFlyweight('a');$flA->operation(--$extrinsicState);$flB=$factory->getFlyweight('b');$flB->operation(--$extrinsicState);$flC=$factory->getFlyweight('c');$flC->operation(--$extrinsicState);$flD=newUnsharedConcreteFlyweight();$flD->operation(--$extrinsicState);
客户真个调用,让外部状态$extrinsicState能够在各个工具之间共享
有点意思吧,这个模式的代码量可不算少当一个运用程序利用了大量非常相似的的工具,工具的大多数状都可变为外部状态时,很适宜享元模式这里的工厂是存储工具列表的,不是像工厂方法或者抽象工厂一样去创建工具的,虽说这里也进行了创建,但如果工具存在,则会直接返回,而且列表也是一贯掩护的享元模式在现实中,大家多少一定用过,各种池技能便是它的范例运用:线程池、连接池等等,其余两个一样的字符串String类型在php或Java中都是可以===的,这也利用到了享元模式,它们连内存地址都是一样的,这不便是一种共享嘛关于享元模式,有一个极其经典的例子,比我下面的例子要好的多,那便是关于围棋的棋盘。围棋只有黑白两色,以是两个工具就够了,接下来呢?改变他们的位置状态就好啦!有兴趣的朋友可以搜搜哈!
Laravel中的IoC容器可以看作是一种享元模式的实现。它把工具保存在数组中,在须要的时候通过闭包机制进行取用,也有一些类有共享一些状态属性的内容。大家可以翻看代码理解理解。
还是说到科技以换壳为本这件事上。毕竟,大家都还是喜好各种颜色的手机来彰显自己的个性。之前说过,如果每种颜色我们都要做一条生产线的话那岂不是一项巨大的投入。还好,每个型号我们的工厂(享元工厂)只生产最基本的背景壳(工具),然后通过专门的印刷线(状态变革)来进行上色不就好啦!
嗯,下一款Iphone早晚也会模拟我们的,看来我们得先把各种金、各种土豪色集齐才行,说不定还能召唤神龙呢!
!
完全代码:https://github.com/zhangyue0503/designpatterns-php/blob/master/13.flyweights/source/flyweights.php
实例果真不出意外的我们还是来发短信,这回的短信依然利用的阿里云和极光短信来进行发送,不过这次我们利用享元模式来实现,这里的享元工厂我们保存了两种不同类型的工具哦,通过内外状态来让它们千变万化吧!
短信发送类图
短信发送享元模式版
完全源码:https://github.com/zhangyue0503/designpatterns-php/blob/master/13.flyweights/source/flyweights-message.php
<?phpinterfaceMessage{publicfunctionsend(User$user);}classAliYunMessageimplementsMessage{private$template;publicfunction__construct($template){$this->template=$template;}publicfunctionsend(User$user){echo'利用阿里云短信向'.$user->GetName().'发送:';echo$this->template->GetTemplate(),PHP_EOL;}}classJiGuangMessageimplementsMessage{private$template;publicfunction__construct($template){$this->template=$template;}publicfunctionsend(User$user){echo'利用极光短信向'.$user->GetName().'发送:';echo$this->template->GetTemplate(),PHP_EOL;}}classMessageFactory{private$messages=[];publicfunctionGetMessage(Template$template,$type='ali'){$key=md5($template->GetTemplate().$type);if(!key_exists($key,$this->messages)){if($type=='ali'){$this->messages[$key]=newAliYunMessage($template);}else{$this->messages[$key]=newJiGuangMessage($template);}}return$this->messages[$key];}publicfunctionGetMessageCount(){echocount($this->messages);}}classUser{public$name;publicfunctionGetName(){return$this->name;}}classTemplate{public$template;publicfunctionGetTemplate(){return$this->template;}}//内部状态$t1=newTemplate();$t1->template='模板1,不错哟!
';$t2=newTemplate();$t2->template='模板2,还好啦!
';//外部状态$u1=newUser();$u1->name='张三';$u2=newUser();$u2->name='李四';$u3=newUser();$u3->name='王五';$u4=newUser();$u4->name='赵六';$u5=newUser();$u5->name='田七';//享元工厂$factory=newMessageFactory();//阿里云发送$m1=$factory->GetMessage($t1);$m1->send($u1);$m2=$factory->GetMessage($t1);$m2->send($u2);echo$factory->GetMessageCount(),PHP_EOL;//1$m3=$factory->GetMessage($t2);$m3->send($u2);$m4=$factory->GetMessage($t2);$m4->send($u3);echo$factory->GetMessageCount(),PHP_EOL;//2$m5=$factory->GetMessage($t1);$m5->send($u4);$m6=$factory->GetMessage($t2);$m6->send($u5);echo$factory->GetMessageCount(),PHP_EOL;//2//加入极光$m1=$factory->GetMessage($t1,'jg');$m1->send($u1);$m2=$factory->GetMessage($t1);$m2->send($u2);echo$factory->GetMessageCount(),PHP_EOL;//3$m3=$factory->GetMessage($t2);$m3->send($u2);$m4=$factory->GetMessage($t2,'jg');$m4->send($u3);echo$factory->GetMessageCount(),PHP_EOL;//4$m5=$factory->GetMessage($t1,'jg');$m5->send($u4);$m6=$factory->GetMessage($t2,'jg');$m6->send($u5);echo$factory->GetMessageCount(),PHP_EOL;//4
解释
代码有点多吧,但实在一共是两种类型的类,天生了四种工具。这里每个类不同的工具是根据模板来区分的这样的组合还是比较方便的吧,再结合别的模式将工厂这里优化一下,嗯,出息不可限量,你们可以想想哦!享元模式适用于系统中存在大量的相似工具以及须要缓冲池的场景,能够降落内存占用,提高效率,但会增加繁芜度,须要分享内外部状态最紧张的特点是有一个唯一标识,当内存中已经有这个工具了,直接返回工具,不用再去创建了下期看点
享元模式的例子说得有点牵强,不过确实这类设计模式在我们日常的开拓中一方面用得不多,另一方面范例的例子又太经典,反正只要记住它的特点就好了,详细在运用的时候说不准写完代码转头一看你会创造这不便是我学过的享元模式嘛!
好了,下一篇我们学习一个也是比较少用而且繁芜的模式,但是大概你也能常常见到哦!
组合模式