一、定义
享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。
分为:单纯享元模式和组享元模式。
一个复合享元对象的所有单纯享元对象元素的外蕴状态都是与复合享元对象的外蕴状态相等的;而一个复合享元对象所含有的单纯享元对象的内蕴状态一般是不相等的,不然就没有使用价值了。
二、优点及缺点
优点:
1、大大减少对象的创建,降低系统的内存,使效率提高。
缺点:
1、提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
三、代码实现:
单纯享元模式:
享元抽象类:
package com.example.demo.sjms.danchunxiangyuanmoshi; /** * @Author: caesar * @Date:2020年11月02日 10:11:45 * @Description: 抽象享元角色 */ public interface PersonInterdface { // 传入外蕴角色 public void say(String name); }
享元实现角色:
package com.example.demo.sjms.danchunxiangyuanmoshi; /** * @Author: caesar * @Date:2020年11月02日 10:11:41 * @Description: 具体享元角色 */ public class Person implements PersonInterdface{ // 传入内蕴角色 private Integer id; public Person(Integer id) { this.id = id; } @Override public void say(String words) { System.out.println("id为"+id+"的员工说"+words); } }
享元工厂:
package com.example.demo.sjms.danchunxiangyuanmoshi; import java.util.HashMap; import java.util.Map; /** * @Author: caesar * @Date:2020年11月02日 10:11:53 * @Description: 享元工厂角色 */ public class PersonFactory { private Map<Integer, PersonInterdface> personMap = new HashMap<Integer, PersonInterdface>(); public PersonInterdface getPersonInterdface(Integer id){ PersonInterdface person = personMap.get(id); if(null == person){ person = new Person(id); personMap.put(id, person); } return person; } }
测试方法:
package com.example.demo.sjms.danchunxiangyuanmoshi; /** * @Author: caesar * @Date:2020年11月02日 10:11:54 * @Description: 测试类 */ public class Test { public static void main(String[] args) { PersonFactory personFactory = new PersonFactory(); PersonInterdface person = personFactory.getPersonInterdface(1); person.say("加油呀!!!"); PersonInterdface person2 = personFactory.getPersonInterdface(1); person.say("加油呀!!!"); System.out.println(person == person2); } }
复合享元模式:
享元抽象角色:
package com.example.demo.sjms.fuhexiangyuanmoshi; /** * @Author: caesar * @Date:2020年11月02日 10:11:45 * @Description: 抽象享元角色 */ public interface PersonInterdface { // 传入外蕴角色 public void say(String name); }
享元实现角色:
package com.example.demo.sjms.fuhexiangyuanmoshi; /** * @Author: caesar * @Date:2020年11月02日 10:11:41 * @Description: 具体享元角色 */ public class Person implements PersonInterdface { // 传入内蕴角色 private Integer id; public Person(Integer id) { this.id = id; } @Override public void say(String words) { System.out.println("id为"+id+"的员工说"+words); } }
复合享元角色:
package com.example.demo.sjms.fuhexiangyuanmoshi; import java.util.HashMap; import java.util.Map; /** * @Author: caesar * @Date:2020年11月02日 11:11:27 * @Description: 复合享元类 */ public class MorePerson implements PersonInterdface{ private Map<Integer, PersonInterdface> personMap = new HashMap<Integer, PersonInterdface>(); public void add(Integer key, PersonInterdface value){ if(null == personMap.get(key)){ personMap.put(key, value); } } @Override public void say(String name) { personMap.forEach((k, v) -> { v.say(name); }); } }
享元工厂角色:
package com.example.demo.sjms.fuhexiangyuanmoshi; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @Author: caesar * @Date:2020年11月02日 10:11:53 * @Description: 享元工厂角色 */ public class PersonFactory { private Map<Integer, PersonInterdface> personMap = new HashMap<Integer, PersonInterdface>(); /** * @Author: caesar * @Date:2020年11月02日 11:11:50 * @Description: 复合享元方法 */ public PersonInterdface getPersonInterdface(List<Integer> idList){ MorePerson morePerson = new MorePerson(); idList.forEach(x ->{ morePerson.add(x,this.getPersonInterdface(x)); }); return morePerson; } /** * @Author: caesar * @Date:2020年11月02日 11:11:05 * @Description: 单纯享元方法 */ public PersonInterdface getPersonInterdface(Integer id){ PersonInterdface person = personMap.get(id); if(null == person){ person = new Person(id); personMap.put(id, person); } return person; } }
测试类:
package com.example.demo.sjms.fuhexiangyuanmoshi; import java.util.ArrayList; import java.util.List; /** * @Author: caesar * @Date:2020年11月02日 10:11:54 * @Description: 测试类 */ public class Test { public static void main(String[] args) { PersonFactory personFactory = new PersonFactory(); List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); PersonInterdface person = personFactory.getPersonInterdface(list); person.say("加油呀!!!"); } }
四、源码级别
五、总结
注意点:1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。 2、这些类必须有一个工厂对象加以控制。3、有大量相同对象时使用。