[工作中的设计模式]享元模式模式FlyWeight

一、模式解析

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=借记卡]]

五、解析

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

时间: 2024-10-12 11:41:58

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

设计模式-享元模式

***********************************************声明****************************************************** 原创作品,出自 "晓风残月xj" 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj). 由于各种原因,可能存在诸多不足,欢迎斧正! *******************************************

小菜学设计模式——享元模式

背景 如果一个应用程序中使用了大量的对象,而大量的这些对象造成了恨得的存储开销时就应该考虑这个新是设计模式:享元模式. 1.使用意图 最大限度地减少了尽可能与其他类似的对象多的数据共享内存的使用,换句话说就是通过共享对象达到系统内维护的对象数量减少从而降低了系统的开销.因为是细粒度的控制,所以享元模式不是控制整个实例共享,那为何不用单例呢?而是只是共享对象的部分,不共享的部分称为对象的外部状态,需要外部动态修改这个共享对象. 2.生活实例 围棋的棋子,如果用编程去实现的话,势必要new出很多实例

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

模式动机 面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.享元模式正是为解决这一类问题而诞生的.享元模式通过共享技术实现相同或相似对象的重用. 在享元模式中可以共享的相同内容称为内部状态(Intrinsic State),而那些需要外部环境来设置的不能共享的内容称为外部状态(Extrinsic State),由于区分了内部状态和外部状态,因此可以通过设置不同的外部状态使得相同的对象可以具有

Java设计模式——享元模式

概述 在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建. 版权说明 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 本文作者:Coding-Naga 发表日期: 2016年4月25日 本文链接:http://blog.csdn.net/lemon_tree12138/article/details/51241598 来源:CSDN 更多内容:分类 >> 设计模式 目录 概述 版权说明 目录

设计模式——享元模式

Flyweight 直译为蝇量.就其表示的模式来说,翻译成享元,确实是不错的 package designpattern.structure.flyweight; public interface Flyweight { void action(int arg); } package designpattern.structure.flyweight; public class FlyweightImpl implements Flyweight { public void action(int

java设计模式--享元模式

享元模式(flyweight) 当需要有很多完全相同或相似的对象需要创建的时候,主要是相似的时候,我们可以用享元模式.尽可能少创建对象,节省内存. 享元模式主要有4中角色 1.享元的工厂 2.抽象享元对象 2.内部状态对象:可以共享的 3.外部状态对象:不可以共享的 下面以围棋的棋子为例:每个棋子都是一个对象,但是每个棋子的大部分都一样,只有颜色,摆放位置不一样,这样就没必要每个棋子都创建一个对象,把相同的和不同的分离开来. //享元类抽象 public interface FlyWeight

设计模式之禅之设计模式-享元模式

一:享元模式定义        --->享元模式(Flyweight Pattern)是池技术的重要实现方式        --->使用共享对象可有效地支持大量的细粒度的对象        --->要求细粒度对象,那么不可避免地使得对象数量多且性质相近,那我们就将些对象的信息分为两个部分:内部状态(intrinsic)与外部状态(extrinsic).                ● 内部状态                        内部状态是对象可共享出来的信息,存储在享元对象

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

题记==============================================================================本php设计模式专辑来源于博客(jymoz.com),现在已经访问不了了,这一系列文章是我找了很久才找到完整的,感谢作者jymoz的辛苦付出哦! 本文地址:http://www.cnblogs.com/davidhhuan/p/4248186.html============================================

iOS设计模式——享元模式

公共交通(如公共汽车)已有一百多年的历史了.大量去往相同方向的乘客可以分担保有和经营车辆(如公共汽车)的费用.公共汽车有多个站台,乘客沿着路线在接近他们目的地的地方上下车.到达目的地的费用仅与行程有关.跟保有车辆相比,乘坐公共汽车要便宜得多.这就是利用公共资源的好处. 在面向对象软件设计中,我们利用公共对象不仅能节省资源还能提高性能.比方说,某个人物需要一个类的一百万个实例,但我们可以把这个类的一个实例让大家共享,而把某些独特的信息放在外部,节省的资源可能相当可观(一个实例与一百万个实例的差别)