定义

享元模式是对象的结构模式,享元模式以共享的方式高效的支持大量的细粒度对象,主要用于减少创建对象的数量,以减少内存占用和提高性能

享元对象能做到共享的关键在于区分了内蕴状态和外蕴状态

内蕴状态是存储在享元对象内部的,并且是不会随环境的改变而有所不同,因此,一个享元对象可以具有内蕴状态并且可以共享

外蕴状态是随着环境的改变而改变的,并且是不可以共享的状态,享元对象的外蕴状态必须是由客户端保存,并且是在享元对象创建之后,在需要使用的时候再传到享元对象内部

外蕴状态不可以影响享元对象的内蕴状态,换句话说,它们是相互独立的

意图

运用共享技术有效地支持大量细粒度的对象

主要解决问题

在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建

何时使用

系统中存在大量的对象,并且消耗了大量的内存,这些对象的状态大部分可以外部化,这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替

优缺点

优点:

大大减少对象的创建,降低系统的内存,使效率提高

缺点:

使得系统更加复杂,为了使对象可以共享,需要将一些状态外部化

结构

涉及的角色:

抽象享元(Flyweight)角色:所有具体享元类的超类,为这些类规定需要实现的接口

具体享元(ConcreteFlyweight)角色:实现抽象享元角色规定的接口,如果有内蕴状态的话,必须为内蕴状态提供存储空间,享元对象的内蕴状态必须与所处的环境无关,从而使得享元对象可以在系统中共存

享元(FlyweightFactory)工厂角色:负责创建和管理享元角色,本角色必须保证享元对象可以被系统适当的共享,当客户端调用享元对象的时候,享元工厂会检查系统中是不是已经有了符合要求的享元对象,如果有了就提供这个对象,如果没有享元工厂就应当创建一个合适的享元对象

客户端(Client)角色:本角色需要维护一个对所有享元对象的引用,需要自行存储所有享元对象的外蕴状态

对应源码如下:

public abstract class Flyweight{

/** 一个示意性的方法,参数state是外蕴状态 */

public abstract void operation(String state);

}

复制代码

public class ConcreteFlyweight extends Flyweight{

private int intrinsicState;

public ConcreteFlyweight(int intrinsicState){

this.intrinsicState = intrinsicState;

}

/**

* 外蕴状态作为参量传入

* 改变方法的行为

* 并不改变对象的内蕴状态

*/

@Override

public void operation(String state){

System.out.println("内蕴状态:" + intrinsicState + ",,外蕴状态:" + state);

}

}

复制代码

public class FlyweightFactory{

private Map map = new HashMap();

private Flyweight flyweight;

public FlyweightFactory(){

}

//内蕴状态作为参量传入

public Flyweight factory(int state){

if (map.containsKey(state)) {

return map.get(state);

} else {

Flyweight fly = new ConcreteFlyweight(state);

map.put(String.valueOf(state), fly);

return fly;

}

}

public void checkFlyweight(){

Flyweight fly;

int i = 0;

Iterator iterator = map.entrySet().iterator();

while (iterator.hasNext()) {

Map.Entry e = (Map.Entry) iterator.next();

System.out.println("Item " + (++i) + ":" + e.getKey());

}

}

}

复制代码

public class Client{

public static void main(String[] args){

FlyweightFactory factory = new FlyweightFactory();

Flyweight flyweight = factory.factory(888);

flyweight.operation("第一次");

flyweight = factory.factory(999);

flyweight.operation("第二次");

flyweight = factory.factory(888);

flyweight.operation("第三次");

System.out.println();

factory.checkFlyweight();

}

}

复制代码

奶茶摊位的例子

在这个奶茶摊位上,有一系列口味的奶茶,客人来了之后拿到奶茶付了钱就走了,奶茶有内蕴状态,也就是它的口味,没有外部环境影响,也就是没有外蕴状态

如果在系统中,对每一杯奶茶都创建一个对象的话,那么就会创建出很多细小的对象出来,如果按照奶茶的口味区分,每一种口味的奶茶都只创建一个对象,然后共享

下面使用代码实现:

抽象享元角色,也就是每一种奶茶口味需要实现的接口:

public abstract class Order{

/** 将咖啡卖给客人 */

public abstract void sellingCoffee();

/** 返回奶茶的口味 */

public abstract String getFlavor();

}

复制代码

具体享元角色,奶茶口味实现抽象享元角色提供的接口:

public class Flavor extends Order{

private String flavor;

public Flavor(String flavor){

this.flavor = flavor;

}

@Override

public void sellingCoffee(){

System.out.println("将奶茶卖给客人,奶茶口味为:" + this.flavor);

}

@Override

public String getFlavor(){

return this.flavor;

}

}

复制代码

摊主提供奶茶,也就是享元工厂,负责创建和管理享元角色:

public class FlavorFactory{

private Order[] flavors = new Flavor[10];

private int ordersMade = 0;

private int totalFlavors = 0;

/** 根据所需要的口味提供奶茶 */

public Order getOrder(String flavor){

if (ordersMade > 0) {

for (int i=0; i

if (flavor.equals(flavors[i].getFlavor())) {

return flavors[i];

}

}

}

flavors[ordersMade] = new Flavor(flavor);

totalFlavors++;

return flavors[ordersMade++];

}

/** 返回所有的奶茶口味 */

public int getTotalFlavors(){

return totalFlavors;

}

}

复制代码

客户端:

public class Client{

private static Order[] flavors = new Flavor[10];

private static int ordersMade = 0;

private static FlavorFactory factory;

private static void taskOrder(String flavor){

flavors[ordersMade++] = factory.getOrder(flavor);

}

public static void main(String[] args){

factory = new FlavorFactory();

taskOrder("原味");

taskOrder("香蕉");

taskOrder("原味");

taskOrder("草莓");

taskOrder("草莓");

for (int i=0; i

flavors[i].sellingCoffee();

}

System.out.println("总共买奶茶人数:" + ordersMade);

System.out.println("总共卖出奶茶口味数:" + factory.getTotalFlavors());

}

}

复制代码

可以看到,虽然客人买了5杯奶茶,但是奶茶的口味只有三种

奶茶店的例子

奶茶摊位没有提供桌椅给客人,也就是没有外部环境影响,现在奶茶店提供了桌椅,那么桌椅就是外蕴状态

抽象享元角色,也就是每一种奶茶口味需要实现的接口:

public abstract class Order{

/** 将咖啡卖给客人 */

public abstract void sellingCoffee(Table table);

/** 返回奶茶的口味 */

public abstract String getFlavor();

}

复制代码

具体享元角色,奶茶口味实现抽象享元角色提供的接口:

public class Flavor extends Order{

private String flavor;

public Flavor(String flavor){

this.flavor = flavor;

}

@Override

public void sellingCoffee(Table table){

System.out.println("将奶茶卖给客人,奶茶口味为:" + this.flavor + ",客人所坐桌子号码为:" + table.getNumber());

}

@Override

public String getFlavor(){

return this.flavor;

}

}

复制代码

奶茶店提供奶茶,也就是享元工厂,负责创建和管理享元角色:

public class FlavorFactory{

private Order[] flavors = new Flavor[10];

private int ordersMade = 0;

private int totalFlavors = 0;

/** 根据所需要的口味提供奶茶 */

public Order getOrder(String flavor){

if (ordersMade > 0) {

for (int i=0; i

if (flavor.equals(flavors[i].getFlavor())) {

return flavors[i];

}

}

}

flavors[ordersMade] = new Flavor(flavor);

totalFlavors++;

return flavors[ordersMade++];

}

/** 返回所有的奶茶口味 */

public int getTotalFlavors(){

return totalFlavors;

}

}

复制代码

环境角色,桌椅:

public class Table{

/** 桌子号码 */

private int number;

public Table(int number){

this.number = number;

}

public int getNumber(){

return number;

}

public void setNumber(int number){

this.number = number;

}

}

复制代码

客户端:

public class Client{

private static Order[] flavors = new Flavor[10];

private static int ordersMade = 0;

private static FlavorFactory factory;

private static void taskOrder(String flavor){

flavors[ordersMade++] = factory.getOrder(flavor);

}

public static void main(String[] args){

factory = new FlavorFactory();

taskOrder("原味");

taskOrder("香蕉");

taskOrder("原味");

taskOrder("草莓");

taskOrder("草莓");

for (int i=0; i

flavors[i].sellingCoffee(new Table(i+1));

}

System.out.println("总共买奶茶人数:" + ordersMade);

System.out.println("总共卖出奶茶口味数:" + factory.getTotalFlavors());

}

}

复制代码

在什么情况下使用享元模式

一个系统中有大量的对象

这些对象消耗大量的内存

这些对象的状态中大部分都可以外部化

这些对象可以按照内蕴状态分为很多组,当把外蕴状态从对象中剔除时,每一个组都可以用一个对象代替

软件系统不依赖这些对象的身份,即这些对象可以是不可分辨的

奶茶店小票代码java_由奶茶店突发奇想开始了Java设计模式:享元模式相关推荐

  1. Unity设计模式——享元模式(附代码)

    Unity设计模式--享元模式(附源码) 享元Flyweight模式是什么 享元模式是一种结构型设计模式, 它摒弃了在每个对象中保存所有数据的方式, 通过共享多个对象所共有的相同状态, 让你能在有限的 ...

  2. 设计模式——享元模式(附代码示例)

    一. 传统方式 以网站项目展示为例,有的要求以新闻形式发布,有的要求以博客形式发布,有的要求以微信公众号形式发布 1. 传统方式解决 给每个网站租用一个空间,直接复制粘贴一份,然后根据客户不同要求,进 ...

  3. 陈臣java_小菜学设计模式——享元模式

    背景 如果一个应用程序中使用了大量的对象,而大量的这些对象造成了恨得的存储开销时就应该考虑这个新是设计模式:享元模式. 1.使用意图 最大限度地减少了尽可能与其他类似的对象多的数据共享内存的使用,换句 ...

  4. java设计模式之工厂模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  5. 『设计模式』写代码偷懒小技巧,程序开发大智慧--享元模式

    23种设计模式+额外常用设计模式汇总 (持续更新) 享元模式 享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能.这种类型的设计模式属于结构型模式,它提 ...

  6. Java设计模式之模板方法模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  7. Java设计模式之策略模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  8. Java设计模式之享元模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

  9. java设计模式之建造者模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...

最新文章

  1. windows10 查看 nvidia driver cuda 版本
  2. Xilinx DMA kernel 驱动详解 (一)
  3. 表格数据清空还能恢复吗_数据恢复大师:清空回收站文件如何恢复?
  4. Unity3D研究院之Editor下监听Transform变化
  5. python3中的type与object
  6. 网易云海外推流部署实践
  7. MySQL 高可用架构在业务层面的应用分析
  8. 机械齿轮网站404单页源码
  9. Linux 关于Transparent Hugepages的介绍
  10. 为节省内存,动态添加view布局和控件
  11. python和java选择哪个-JAVA和Python哪个好就业?
  12. 洛谷 P2317 [HNOI2005]星际贸易 解题报告
  13. 基于 Flink 的典型 ETL 场景实现方案
  14. python pip 快速安装第三方库和下载好whl文件
  15. 【Caffe安装】caffe安装系列——史上最详细的安装步骤
  16. php图片镜像翻转,怎么把视频镜面翻转/视频水平翻转的教程
  17. Python数据分析案例篇(一)泰坦尼克号数据分析
  18. 内网入口——代理搭建端口转发
  19. uni-app - 苹果安卓系统监听物理返回按键(手机左滑返回监听)
  20. pve中新加一块硬盘_J1900工控主板装PVE虚拟机搭爱快LEDE双软路由系统小记

热门文章

  1. jQuery实现可拖动控制进度条
  2. DATEDIFF 和DATEADD 的用法和区别
  3. Selenium的下载
  4. CST仿真同轴馈电的微带天线
  5. Codeforces - Masha and Cactus
  6. CUDA从入门到精通
  7. 微信小程序滑动导航栏
  8. 斯坦福研究人员让AI看了100部好莱坞大片,培养出了一个“吻戏识别大师”
  9. 【Auto CAD】Architecture2019 (Win 10 X 64位)中文版/英文版下载和破解安装
  10. flask ajax 上传 图片,flask jQuery ajax 上传文件