一、模式解析

Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意。享元模式是对象的结构模式。享元模式以共享的方式高效地支持大量的细粒度对象。

享元模式:主要为了在创建对象时,对共有对象以缓存的方式进行保存,对外部对象进行单独创建

模式要点:

1、享元模式中的对象分为两部分:共性部分和个性化部分,共性部分就是每个对象都一致的或者多个对象可以共享的部分,个性化部分指差异比较大,每个类均不同的部分

2、共性部分的抽象就是此模式介绍的享元对象

3、享元对象一般通过一个享元工厂进行创建和保存

4、享元工厂根据享元对象的多少,实现一个单例或者多例模式,来创建享元对象

5、享元对象可以预先设定好在享元工厂里,也可以创建一个集合,每次创建对象时,查看享元对象是否存在,不存在则进行添加

二、模式代码

1、创建享元接口

package flyweight.patten;
//享元接口
public interface FlyWeight { public void opertion();
}

2、创建具体享元类

package flyweight.patten;

public class ConcreteFlyWeight implements FlyWeight {
public String name;
public ConcreteFlyWeight(String name){
this.name=name;
}
@Override
public void opertion() {
System.out.println("执行享元类");
}
}

3、创建享元工厂

package flyweight.patten;

import java.util.HashMap;
import java.util.Map; //享元工厂,为客户端提供享元类
public class FlyWeightFactory { //使用内部map,保证享元对象只被创建一次
private Map<String,FlyWeight> map=new HashMap<String,FlyWeight>(); public FlyWeight getFlyWeight(String name){
FlyWeight flyWeight=map.get(name);
if(map.get(name)==null||map.get(name).equals("")){
flyWeight=new ConcreteFlyWeight(name);
map.put(name, flyWeight);
}
return flyWeight;
} }

5、客户端

package flyweight.patten;

public class Client {
public static void main(String[] args) {
FlyWeightFactory factory=new FlyWeightFactory();
FlyWeight flyWeight1=factory.getFlyWeight("张三");
FlyWeight flyWeight2=factory.getFlyWeight("李四");
FlyWeight flyWeight3=factory.getFlyWeight("张三");
System.out.println(flyWeight1==flyWeight2);
System.out.println(flyWeight1==flyWeight3);
}
}

6、执行结果,可以看到,如果姓名相同,每次引用的享元对象都是一样的,符合多例模式

false
true

注:此模式的标准代码为单纯的享元模式,并不完全符合我们上边的模式要点,因为他创建的对象参数全部为享元内容,所以我们在后边的实例中编写一个完全的享元模式代码。

三、应用场景

享元模式的应用比较广泛,类似与数据库的外键关联关系,所以我们以工作中最常见的银行卡举例:

  客户账户属性分为:银行卡种类,银行卡名称,银行卡号,余额,客户姓名等因素。在创建卡对象时候,由于卡种类和名称对于每个银行仅有几种,所以创建一个享元对象进行保存。

四、模式代码

1、创建银行卡类,也就是享元对象

package flyweight.example;
/**
* 卡类型
* @author lenovo
*
*/
public class Card {
private String cardType;
private String cardName;
public String getCardName() {
return cardName;
} public void setCardName(String cardName) {
this.cardName = cardName;
} public String getCardType() {
return cardType;
} public void setCardType(String cardType) {
this.cardType = cardType;
}
public Card(String cardType,String cardName){
this.cardType=cardType;
this.cardName=cardName;
} @Override
public String toString() {
return "CardType [cardType=" + cardType + ", cardName=" + cardName + "]";
} }

2、创建账户接口

package flyweight.example;
/**
* 账户接口
* @author lenovo
*
*/
public interface CountInterface {
/**
* 显示卡内容
*/
public void show() ;
}

3、创建账户类

package flyweight.example;

import java.math.BigDecimal;

/**
* 具体账户属性
* @author lenovo
*
*/
public class ConcreteCount implements CountInterface {
private String cardNo;
private BigDecimal balance;
private Card card;
/**
* 根据参数创建用户对象
* @param cardNo
* @param balance
* @param cardType
*/
public ConcreteCount(String cardNo, BigDecimal balance, Card card) {
this.cardNo = cardNo;
this.balance = balance;
this.card = card;
} @Override
public String toString() {
return "ConcreteCount [cardNo=" + cardNo + ", balance=" + balance + ", card=" + card + "]";
} @Override
public void show() {
System.out.println(this.toString()); } }

5、创建享元工厂,享元工厂返回客户账户实例,在创建客户账户时,首先判断卡属性是否存在,存在就直接从享元对象中获取卡属性,否则创建新的卡

package flyweight.example;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map; /**
* 享元工厂,主要用于创建对象
* @author lenovo
*
*/
public class CountFactory {
//保存享元对象的map
Map<String,Card> cardTypeMap=new HashMap<String, Card>(); public ConcreteCount getConcreteCount(String cardNo, BigDecimal balance,String cardType,String cardName){ Card card=null;
//判断享元对象是否已经存在,如果存在则使用,不存在则额外创建
if(cardTypeMap.get(cardType+cardName)!=null){
card=cardTypeMap.get(cardType+cardName);
}else {
card=new Card(cardType, cardName);
cardTypeMap.put(cardType+cardName, card);
} return new ConcreteCount(cardNo, balance, card); }
}

5、客户端

package flyweight.example;

import java.math.BigDecimal;

public class CardTest {

    /**
* 测试享元模式
* @param args
*/
public static void main(String[] args) {
CountFactory factory=new CountFactory();
ConcreteCount count=factory.getConcreteCount("001", new BigDecimal(100), "1", "信用卡");
ConcreteCount count2=factory.getConcreteCount("002", new BigDecimal(200), "2", "借记卡");
ConcreteCount count3=factory.getConcreteCount("003", new BigDecimal(300), "1", "信用卡");
ConcreteCount count4=factory.getConcreteCount("004", new BigDecimal(400), "2", "借记卡"); count.show();
count2.show();
count3.show();
count4.show(); } }

6、结果

ConcreteCount [cardNo=001, balance=100, card=CardType [cardType=1, cardName=信用卡]]
ConcreteCount [cardNo=002, balance=200, card=CardType [cardType=2, cardName=借记卡]]
ConcreteCount [cardNo=003, balance=300, card=CardType [cardType=1, cardName=信用卡]]
ConcreteCount [cardNo=004, balance=400, card=CardType [cardType=2, cardName=借记卡]]

五、解析

如同第三部分所说,享元模式大都是以数据库外键形式体现在系统中,所以在系统中使用享元思想的很多,但是使用享元对象标准模式写法的还是比较少,所以设计模式还是要注重思想。

[工作中的设计模式]享元模式模式FlyWeight的更多相关文章

  1. 深入浅出设计模式——享元模式(Flyweight Pattern)

    模式动机 面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.享元模式正是为解决这一类问题而诞生 ...

  2. C++设计模式——享元模式

    本文版权归果冻说所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.如果这篇文章对你有帮助,你可以请我喝杯咖啡. » 本文链接:http:// ...

  3. java设计模式——享元模式

    一. 定义与类型 定义:提供了减少对象数量从而改善应用所需的对象结构的方式,运用共享技术有效地支持大量细粒度的对象 类型:结构性 二. 使用场景 (1)  常常应用于系统底层的开发,以便解决系统的性能 ...

  4. 【设计模式】Java设计模式 - 享元模式

    Java设计模式 - 享元模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 原创作品,更多关注我CSDN: 一个有梦有戏的人 准备将博客园.CSDN一起记录分享自己 ...

  5. C#设计模式-享元模式

    在软件开发过程,如果我们需要重复使用某个对象的时候,如果我们重复地使用new创建这个对象的话,这样我们在内存就需要多次地去申请内存空间了,这样可能会出现内存使用越来越多的情况,这样的问题是非常严重,然 ...

  6. 8. 星际争霸之php设计模式--享元模式

    题记==============================================================================本php设计模式专辑来源于博客(jymo ...

  7. iOS设计模式 - 享元

    iOS设计模式 - 享元 原理图 说明 享元模式使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件:它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件.通常物件中的部分 ...

  8. Java设计模式-享元模式(Flyweight)

    享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用. FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查 ...

  9. java设计模式---享元模式

    享元模式 顾名思义:共享元对象.如果在一个系统中存在多个相同的对象,那么只需要共享一份对象的拷贝,而不必为每一次使用创建新的对象. 享元模式是为数不多的.只为提升系统性能而生的设计模式.它的主要作用就 ...

随机推荐

  1. 错误信息:内存位置访问无效。 (Exception from HRESULT: 0x800703E6)

    错误提示: 错误信息:内存位置访问无效. (Exception from HRESULT: 0x800703E6) 异常类型:System.BadImageFormatException 堆栈跟踪: ...

  2. animate对颜色设置不起作用

    今天了解了一下stop的使用方法,但是实例中加入color:red的时候,动画效果没有实现,具体实例如下: http://jsbin.com/fezaroyene/edit?html,js,outpu ...

  3. ubuntu14.04 下安装有道词典

    安装步骤 1.ubuntu14.04.1版本下是不能直接安装有道词典的,首先需要把14.04.版升级为14.04.2版. 在终端窗口中输入以下命令: sudo apt-get update sudo ...

  4. IBatis 2.x 和 MyBatis 3.0.x 的区别(从 iBatis 到 MyBatis)

    从 iBatis 到 MyBatis,你准备好了吗? 对于从事 Java EE 的开发人员来说,iBatis 是一个再熟悉不过的持久层框架了,在 Hibernate.JPA 这样的一站式对象 / 关系 ...

  5. Dijkstra算法

    Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. /*图的邻接矩阵表示*/typedef ...

  6. 前端工具之Gulp

    Gulp是一款前端自动化的工具,如果能熟练使用Gulp来进行开发一定可以节省很多的时间,也可以快速的提高工作效率. 在使用Gulp之前就是要配置好Gulp安装的环境,这是我们能使用Gulp快速开发的第 ...

  7. 【bzoj2318】Spoj4060 game with probability Problem

    题目描述 Alice和Bob在玩一个游戏.有n个石子在这里,Alice和Bob轮流投掷硬币,如果正面朝上,则从n个石子中取出一个石子,否则不做任何事.取到最后一颗石子的人胜利.Alice在投掷硬币时有 ...

  8. css 强制 中文、英文 换行

    .livechat-text a { display: block; word-break:break-all; /* 英文换行 */ white-space:normal; /* 中文换行 */ } ...

  9. and or bool and a or b 原理解释

    python 中的and从左到右计算表达式,若所有值均为真,则返回最后一个值,若存在假,返回第一个假值. or也是从左到有计算表达式,返回第一个为真的值. 代码如下: IDLE 1.2.4>&g ...

  10. Java 中的内存泄露

    1.当你完成对流的读写时,应该通过调同close方法来关闭它,这个调用会释放掉十分有限的系统资源,否则,如果一个应用程序打开了过多的流而没有关闭,那么系统资源将被耗尽.