java设计模式--享元模式

享元模式

  享元模式是对象结构型模式,享元模式运用共享技术有效地支持大量细粒度的对象。说到享元模式,立马能够想到的就是池技术了,String常量池、数据库连接池、线程池等等都是运用了享元模式, 享元模式是池技术实现的重要方式。

  举个例子,String对象是final的不可变的,我们每次创建一个字符串对象的时候,JAVA都会确保一个字符串常量在常量池中有且只有一个拷贝,例如String a="admin"  这个admin就是一个字符串常量。

public class StringTest {
    public static void main(String[] args) {
        String a = "admin";
        String b = "admin";
        System.out.println(a == b);
    }
}

  上面的例子执行结果为:true,也就是说对象a和对象b引用了常量池中同一个字符串admin,这种方式避免了新建过多的对象而产生内存损耗问题。

享元模式的适用性

  享元模式中比较重要的概念就是内部状态和外部状态,内部状态存储于享元对象中,它包含了独立于享元对象场景的信息,这些信息可以使得享元对象被共享,而外部状态取决于享元对象的场景,并根据场景的变化而变化,所以不能够共享。所以在以下情况都成立的情况下使用享元模式会带来极大的便利:

  • 一个应用程序使用了大量的对象。

  • 完全由于使用大量的对象,造成很大的存储开销。

  • 对象的大多数状态都可变为外部状态。

  • 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。

 

 享元模式的结构图

在享元模式中总共有四类角色:

1、抽象享元角色(Flyweight):该对象描述了一个接口,该接口可以接受并且作用于外部状态。

2、具体享元角色(ConcreteFlyweight):该对象实现了Flyweight的接口,同时如果该对象包含内部状态的话则存储好该对象的内部状态。

3、不共享的具体享元角色(UnsharedConcreteFlyweight):该对象也实现了Flyweight的接口,但是该角色一般不会出现在享元角色工厂中,即不提供共享。

4、享元角色工厂(FlyweightFactory):该对象创建并且管理Flyweight,同时保证外部合理的共享Flyweight。

 

享元模式的示例

抽象享元角色类,是所有相同种类享元角色的超类或者接口。

 

public interface Flyweight {
    public void Operation(String exState);
}

 

具体享元角色类,实现Flyweight的接口并且为内部状态inState提供存储空间

public class ConcreteFlyweight implements Flyweight {
    private String inState;

    public ConcreteFlyweight(String inState) {
        this.inState = inState;
    }

    @Override
    public void Operation(String exState) {
        System.out.println("内部状态为:" + inState + "外部状态为:" + exState);
    }
}

不共享的具体享元角色类,不提供共享的其他类享元角色

public class UnshareConcreteFlyweight implements Flyweight {
    private String allstate;

    public UnshareConcreteFlyweight(String allstate) {
        this.allstate = allstate;
    }

    @Override
    public void Operation(String exState) {

    }
}

享元角色工厂类,提供创建、管理、合理共享享元角色

public class FlyweightFactory {
    public static HashMap<String, Flyweight> pool = new HashMap<>();

    public static Flyweight getFlyweight(String inState) {
        Flyweight fly = pool.get(inState);
        if (fly == null) {
            fly = new ConcreteFlyweight(inState);
            pool.put(inState, fly);
        }
        return fly;
    }
}

最后通过客户端测试享元模式的效果

public class Client {
    public static void main(String[] args) {

        Flyweight fly1 = FlyweightFactory.getFlyweight("a");
        fly1.Operation("1");
        Flyweight fly2 = FlyweightFactory.getFlyweight("a");
        fly2.Operation("1");
        System.out.println(fly1==fly2);
        Flyweight fly3 = FlyweightFactory.getFlyweight("b");
        fly3.Operation("2");
    }
}


执行结果为:
内部状态为:a外部状态为:1
内部状态为:a外部状态为:1
true
内部状态为:b外部状态为:2

 

 

 

享元模式的优缺点

  1. 通过使用享元模式,该模式大大的减少了对象的创建和销毁过程,这种方式节约了系统的内存,同时在某些程度上提高了系统的执行效率。
  2. 通过使用享元模式也增加了系统的复杂性,同时将一类对象的外部状态和内部状态分离开,增加了系统对外部状态的计算时间,通过计算时间来换取对外部状态的存储。

 

posted on 2019-07-22 21:07  会飞的小杰  阅读(131)  评论(0)    收藏  举报

导航