Java设计模式(12)之享元模式

享元模式

享元模式又称为轻量级模式,享元模式通过资源共享的方式,实现大量细粒度对象的复用,从而减少同类对象的多次创建,减少内存的占用和提高程序的运行速度。

类型:

结构型模式

享元模式的状态:

  • 内部状态/内蕴状态(Internal State):内部状态都存储在享元对象的内部,并且不会随着环境的改变而改变,内部状态便是可以共享的状态,一般通过构造方法或者setter方法传入。
  • 外部状态/外蕴状态(External State): 外部状态必须由客户端保存,会随着环境的改变而改变,外部状态是不可以共享的,一般享元对象创建之后,根据需要进行参数的传入。并且外部状态的传入不能影响内部状态,他们之间是相互独立的。

享元模式分类:

  • 单纯的享元模式:即所有的享元对象都是可以共享的。
  • 复合的享元模式:顾名思义,就是将多个单纯的享元对象组合到一起,复合的享元对象是不可以共享的,但是每个部分又是可以共享的单纯的享元对象。

单纯的享元模式:

单纯的享元模式的角色:

  • 抽象的享元接口(Flyweight):规定具体实现方法的公共接口
  • 具体享元对象(ConcreteFlyweight):实现抽象的享元接口,同时遵守享元对象的一定的规则。
  • 享元工厂(FlyweightFactory):负责创建和管理享元对象。

单纯的享元模式关系图:

这里写图片描述

单纯的享元模式示例:

Flyweight接口:

/**
 * Create by zhaihongwei on 2018/3/22
 */
public interface Flyweight {

    void operation(String externalState);
}

具体的ConcreteFlyweight对象:

/**
 * Create by zhaihongwei on 2018/3/22
 */
public class ConcreteFlyweight implements Flyweight {

    private String internalState;

    /**
     * 构造函数的方式传入内部状态
     * @param internalState 内部状态
     */
    public ConcreteFlyweight(String internalState) {
        this.internalState = internalState;
    }

    /**
     * 外部状态通过普通方法参数的形式传入
     * 从而改变具体方法的行为,但是不改变内部状态
     * @param externalState 外部状态
     */
    @Override
    public void operation(String externalState) {
        System.out.println("internalState:" + internalState);
        System.out.println("externalState:" + externalState);
    }
}

FlyweightFactory工厂对象:

/**
 * Create by zhaihongwei on 2018/3/22
 */
public class FlyweightFactory {

    /**
     * 通过HashMap作为容器,保存具体的享元对象
     */
    private Map<String,Flyweight> flyweightMap = new HashMap<>();

    public Flyweight getFlyweight(String internalState) {
        // 先从HashMap容器中寻找有没有
        Flyweight flyweight = flyweightMap.get(internalState);
        // 这里没有考虑对线程同时访问的情况,具体可以使用单例模式。
        if(flyweight == null) {
            flyweight = new ConcreteFlyweight(internalState);
            flyweightMap.put(internalState,flyweight);
        }
        return flyweight;
    }
}

测试类:

/**
 * Create by zhaihongwei on 2018/3/22
 */
public class Client {

    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();

        Flyweight flyweight = factory.getFlyweight("first_internalState");
        flyweight.operation("first_externalState");
        System.out.println(flyweight);
        System.out.println("--------------------------------------------");
        flyweight.operation("second_externalState");
        System.out.println(flyweight);
    }
}

测试结果:

internalState:first_internalState
externalState:first_externalState
flyweight.ConcreteFlyweight@606d8acf
--------------------------------------------
internalState:first_internalState
externalState:second_externalState
flyweight.ConcreteFlyweight@606d8acf

可以看出享元对象的内部属性没有改变,并且享元对象没有重新创建,即共享的,但是外部属性是可以变化的。

复合的享元模式

复合的享元模式的角色:

  • 抽象的享元接口(Flyweight):规定具体实现方法的公共接口
  • 单纯的享元对象(ConcreteFlyweight):实现抽象的享元接口,同时遵守享元对象的一定的规则。
  • 复合的享元对象(CompositeConcreteFlyweight):复合的享元对象是不可以共享的,但是每一个部分又是可以共享的。
  • 享元工厂(FlyweightFactory):负责创建和管理单纯享元对象和复合享元对象。

复杂的享元模式关系图:

这里写图片描述

复合的享元模式示例:

Flyweight接口:

/**
 * Create by zhaihongwei on 2018/3/22
 */
public interface Flyweight {

    void operation(String externalState);
}

CompositeConcreteFlyweight复合享元对象:

/**
 * Create by zhaihongwei on 2018/3/22
 */
public class CompositeConcreteFlyweight implements Flyweight{

    private Map<String,Flyweight> compositeConcreteFlyweight = new HashMap<>();

    /**
     * 添加单纯的享元对象
     * @param internalState 内部状态
     * @param flyweight 单纯的享元对象
     */
    public void putFlyweight(String internalState,Flyweight flyweight) {
        compositeConcreteFlyweight.put(internalState,flyweight);
    }

    /**
     * 获取复合享元对象中的一个单纯的享元对象
     * @param internalState
     * @return
     */
    public Flyweight getFlyweight(String internalState) {
        return compositeConcreteFlyweight.get(internalState);
    }

    @Override
    public void operation(String externalState) {
        // 遍历复合的享元对象中包含的每个单纯的享元对象。
        for (String internalState : compositeConcreteFlyweight.keySet()) {
            Flyweight flyweight = compositeConcreteFlyweight.get(internalState);
            flyweight.operation(externalState);
        }
    }
}

复合享元工厂:其中包含了单纯享元对象和复合享元对象的获取方法

/**
 * Create by zhaihongwei on 2018/3/22
 */
public class FlyweightFactory {

    /**
     * 通过HashMap作为容器,保存具体的享元对象
     */
    private Map<String,Flyweight> flyweightMap = new HashMap<>();

    /**
     * 获取单纯的享元对象
     * @param internalState 内部状态
     * @return
     */
    public Flyweight getFlyweight(String internalState) {
        // 先从HashMap容器中寻找有没有
        Flyweight flyweight = flyweightMap.get(internalState);
        // 这里没有考虑对线程同时访问的情况,具体可以使用单例模式。
        if(flyweight == null) {
            flyweight = new ConcreteFlyweight(internalState);
            flyweightMap.put(internalState,flyweight);
        }
        return flyweight;
    }

    /**
     * 获取复合的享元对象
     * @param internalStates 多个单纯的享元对象的内部状态
     * @return
     */
    public Flyweight getCompositeFlyweight(List<String> internalStates) {
        CompositeConcreteFlyweight ccFlyweight = new CompositeConcreteFlyweight();
        for (String internalState : internalStates) {
            ccFlyweight.putFlyweight(internalState,getFlyweight(internalState));
        }
        return ccFlyweight;
    }

}

测试类:

/**
 * Create by zhaihongwei on 2018/3/22
 */
public class Client {

    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        List<String> internalStates = new ArrayList<>();
        internalStates.add("first_internalState");
        internalStates.add("second_internalState");

        CompositeConcreteFlyweight compositeFlyweightA = (CompositeConcreteFlyweight) factory.getCompositeFlyweight(internalStates);
        CompositeConcreteFlyweight compositeFlyweightB = (CompositeConcreteFlyweight) factory.getCompositeFlyweight(internalStates);
        System.out.println("compositeFlyweightA和compositeFlyweightB是和可以共享的嘛?" + (compositeFlyweightA==compositeFlyweightB));
        System.out.println("-----------------------------------------------");
        System.out.println("compositeFlyweightA中的first_internalState和compositeFlyweightB中的first_internalState是可以共享的嘛?" + (compositeFlyweightA.getFlyweight(internalStates.get(0))==compositeFlyweightB.getFlyweight(internalStates.get(0))));
    }
}

测试结果:

compositeFlyweightA和compositeFlyweightB是和可以共享的嘛?false
-----------------------------------------------
compositeFlyweightA中的first_internalState和compositeFlyweightB中的first_internalState是可以共享的嘛?true

从测试结果可以得出,复合的享元对象是不可以共享的,但是复合享元对象中的每一个单纯的享元对象的可以共享的。

个人感想:

至此7中结构型模式学完,下面将进入11种行为型模式的学习,加油!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值