【设计模式】享元模式
享元模式理解
那么享元模式大概就是这个意思,抽取相同的属性放入一个容器以便共享,并且可以保证该属性不会随外部环境变化而变化。
说的可能不好理解,用大白话举个例子
-
创建一个用户user类,里面有属性:体重weight、年龄age、性别sex,还有一个获取用户信息的方法getUserMsg。
-
创建一个HashMap,里面的key存年龄,value存user对象。这个user对象里除了年龄属性是有的,其他属性都为空,且年龄属性值就等于key的值。
-
创建多个user对象,每次创建的时候需要指定年龄并通过年龄先去判断map中是否有相同年龄的对象,如果有,就拿出来用,如果没有就新建。
通过上面的例子可以看出,这种模式,特别适合 系统中有大量相似对象且这些对象消耗了大量的内存的时候,以此来减少对象的创建,降低系统的内存。
在jvm中,有串池的概念,就是创建一个String类型的字符串的时候,如果串池中有一样的字符串,就不会创建,如果没有才会创建并放在串池中。
在数据库中,数据库连接池的概念,也是一个效果。
这里还要提两个概念:
内部状态 :不会随着环境的改变而改变
-
创建一个抽象用户接口,里面有一个获取信息的抽象方法
目的是可以通过此方法来实现某些特定的业务
-
创建一个用户类实现抽象用户接口,定义三个属性,其中体重和性别都是固定的,年龄是可以变化的。并接着定义一个参数为age的有参构造方法,重写接口中的方法。
-
创建一个创建用户的工厂类,定义一个以age为key,user对象为value的hashmap,并提供一个获取用户的方法,方法里定义逻辑为,如果没有此年龄的对象就新建一个并放入map中,如果有就直接从map中获取。
-
创建一个测试类,使用工厂类中的创建用户的方法创建四个用户,其中两个为重复的。
-
最后可以看到结果是,共创建了三个对象,而不是四个,第四个对象创建的时候发现map中有相同age的,所以直接就从map获取了。
-
public interface AbstractUser { //可以通过这里的抽象方法,目的是为了实现某些特定的业务,这里将功能定义成获取用户的信息 void getUserMsg(); }
@Data public class User implements AbstractUser { //内部状态 不会随着环境的改变而改变 private final String weight="60kg"; private final String sex="男"; //外部状态 随着环境的改变而改变的 private Integer age; //参数为age的构造方法 public User(Integer age) { this.age = age; } //特定业务逻辑的具体实现 @Override public void getUserMsg() { System.out.println("用户信息为:weight=" + weight + " age=" + age + " sex=" + sex); } }
public class UserFactory { //定义一个HashMap用来存储所有的共享对象 private static final HashMap<Integer, User> userMap = new HashMap<>(); //工厂类获取用户的方法 public static User getUser(Integer age){ //先判断map里是否有 User user = (User) userMap.get(age); if(user == null){ //map里没有就新创建一个 user = new User(age); userMap.put(age, user); System.out.println("新创建了一个用户:"+user); }else{ System.out.println("使用已创建的用户:"+user); } return user; } }
public class Test { public static void main(String[] args) { //根据年龄创建四个对象 //可以看到在创建最后一个的时候因为在map中有相同年龄的对象,所以没有新建 User user1 = UserFactory.getUser(21); User user2 = UserFactory.getUser(22); User user3 = UserFactory.getUser(23); User user4 = UserFactory.getUser(21); user1.getUserMsg(); user2.getUserMsg(); user3.getUserMsg(); user4.getUserMsg(); } }
//效果 新创建了一个用户:User(weight=60kg, sex=男, age=21) 新创建了一个用户:User(weight=60kg, sex=男, age=22) 新创建了一个用户:User(weight=60kg, sex=男, age=23) 使用已创建的用户:User(weight=60kg, sex=男, age=21) 用户信息为:weight=60kg age=21 sex=男 用户信息为:weight=60kg age=22 sex=男 用户信息为:weight=60kg age=23 sex=男 用户信息为:weight=60kg age=21 sex=男