设计思想学习—享元模式

享元模式

大话设计模式上举得是大量的私人项目,这点很是羡慕,没有私人项目的经验所以只能干瞪眼了喽。

享元模式实现相同或者相似对象的重用。也就是说实现相同或者相似对象的代码共享。

享元模式(Flyweight):运用共享技术有效地支持大量细粒度的对象。

套用大话设计模式的一段话就是:

享元模式可以避免大量非常相似类的开销。

在程序设计中,有时需要生成大量细粒度的类实例来表示数据。

如果能发现这些实例除了几个参数外基本相同,有时就能够大幅度地减少需要实例化的类的数量。

如果能把那些参数移到类实例的外面,在方法调用时将他们传递进来,就可以通过共享大幅度地减少单个实例的数目。

从几个参数外基本相同这句话不难看出,享元模式所需的状态有两部分,分别是相同的内部和不同的外部。

这里出现了几个名词,首先我们来举个栗子说明下粒度的问题:

就比如说车,大家都知道公路上的车颜色有很多种,但是他们都是车,在这里就可以认为是粗粒度的,而颜色这些就可以认为是细粒度的。

然后就是内外部状态:

内部状态就是共享的部分也就是相同的部分。

外部状态就是随着坏境改变的部分

现在来看下享元模式组成:

  • 抽象享元类(Flyweight):所有具体享元类的超类或者接口,通过这个接口,Flyweight可以接受并作用于外部专题

  • 具体享元类(ConcreteFlyweight):指定内部状态,为内部状态增加存储空间。

  • 非共享具体享元类(UnsharedConcreteFlyweight):指出那些不需要共享的Flyweight子类。

  • 享元工厂类(FlyweightFactory):用来创建并管理Flyweight对象,它主要用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory就会提供一个已经创建的Flyweight对象或者新建一个(如果不存在)。

享元模式最重要的就是享元工厂类了,它是维护实例的。

  • 当实例不存在时,就创建一个放入享元池。

  • 当实例存在,就直接从享元池中取出实例来用。

这个跟java中String的工作方式一样,下面代码他们输出的是true因为指向的是同一个地址:

String one="享元模式";
String two="享元模式";
System.out.println(one == two);

同样的在给String赋值的时候会在内存中去查找是否存在此对象,如果不存在则创建然后指向这个地址,如果存在直接指向。

下面我们来看一下享元模式的UML图

设计思想学习—享元模式_第1张图片

在就是上面案例的代码实现:

//抽象享元类,例子是车
interface Car{
    void getCar();
}
//具体享元类,例子是跑车
class Roadster implements Car{
    private String color;
    public Roadster(String color){
        this.color=color;
    }
    @Override
    public void getCar() {
        System.out.println("获得一辆"+color+"跑车");  
    }
}
//享元工厂类
class CarFactory{
    public static  Map map=new HashMap();
    public static Car getACar(String color){
        //判断有无同颜色的车
        if(!map.containsKey(color)){
            map.put(color, new Roadster(color));
        }
        return (Car)map.get(color);
    }
    public static int getKind(){
        return map.size();
    }
}
public class Client {
    public static void main(String[] args) {
        Car car1=CarFactory.getACar("黄色");
        car1.getCar();
        Car car2=CarFactory.getACar("黄色");
        car2.getCar();
        Car car3=CarFactory.getACar("蓝色");
        car3.getCar();
        Car car4=CarFactory.getACar("红色");
        car4.getCar();
        System.out.println("一共获得"+CarFactory.getKind()+"种颜色跑车");
    }
}

输出是
获得一辆黄色跑车
获得一辆黄色跑车
获得一辆蓝色跑车
获得一辆红色跑车
一共获得3种颜色跑车

很明显可以看出,不用创建很多实例了。

享元模式的优点是:

  • 可以减少很多相似对象,减少系统的内存消耗。

  • 使用了内外部的模式且相对的比较独立,所以享元对象能够在不同的坏境中被共享。

至于适用范围,不说也很清楚啦,只要能发挥它优势的地方都可以使用,也就是说一个系统中存在大量相似或相同对象的时候就可以使用了。

你可能感兴趣的:(学习笔记)