Java 设计模式之享元模式的详解(结构模式)
2016-07-31 18:26
651 查看
享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用
享元模式的角色有:
抽象享元(Flyweight)角色:是给实现享元提供的接口。
具体享元(ConcreteFlyweight)角色:实现抽象角色,此对象必须是共享的,所含的状态必须是内部状态。
不共享享元(UnSharedConcreteFlyweight)角色:此对象不可共享,不是所有实现抽象享元接口的的对象都要共享,此对象通常将ConcreteFlyweight作为组成元素。
享元工厂(FlyweightFactory)角色:负责创建和管理享元角色,确保合理共享。
客户端(Client)角色:维持一个Flyweight对象的引用,计算或存储一个(多个)外部存储状态。
享元模式的类图如下:
享元模式在java.lang.String设计上的使用,我们知道java中字符串始终保持共享一份,如下面代码片段:
String m = "a";
String n = "a";
System.out.println(m==n);
这样会输出true,说明m和n指向了同一个实例,内存中也只有一个"a"。这就是享元模式在String上的使用。
享元模式在文字编辑存贮过程中的使用,这里假定文章由行对象组成,行对象由若干个字符对象组成,但是如果每个字符都保存自己的对象,那么一篇文章成千上万个字符对象,这样严重消耗系统内存,造成不可接受的运行时开销,好的方法是利用享元模式,只保存ASCII字符编码值,作为内部不变的状态,对当个字符对象进行共享,而相对字符颜色、大小这样的格式化数据作为外部状态,由客户端维护,运行时由外部传入即可。每个行作为不可共享享元对象,它是由享元对象(字符对象)组合而成的。
举例代码如下:
抽象享元角色:
public interface Glyph {
public abstract void draw(Context context);
}具体享元角色:
public class Row implements Glyph {
private List<Character> list = new ArrayList<>();
@Override
public void draw(Context context) {
// TODO Auto-generated method stub
}
public Row() {
}
public void setCharacter(Glyph r) {
list.add((Character) r);
}
public int getSize() {
return list.size();
}
public String getRow() {
StringBuilder sb = new StringBuilder();
for (Character g : list) {
sb.append(g.getC());
}
return sb.toString();
}
}享元工厂角色:
public class GlyphFactory {
private Map<String, Glyph> map = new HashMap<>();
public Glyph getGlyph(Context context) {
String cStr = context.getC() + "";
Glyph gl = map.get(cStr);
if (gl == null) {
gl = new Character(context.getC());
map.put(cStr, gl);
}
gl.draw(context);
return gl;
}
}数据类:
public class Context {
private int size;
private char c;
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public char getC() {
return c;
}
public void setC(char c) {
this.c = c;
}
public Context(int size, char c) {
super();
this.size = size;
this.c = c;
}
}
客户端角色:
public class Client {
public static void main(String[] args) {
Row r = new Row();
GlyphFactory factory = new GlyphFactory();
Context context1 = new Context(12, 'a');
Glyph gly1 = factory.getGlyph(context1);
r.setCharacter(gly1);
Context context2 = new Context(13, 'a');
Glyph gly2 = factory.getGlyph(context2);
r.setCharacter(gly2);
Context context3 = new Context(13, 'b');
Glyph gly3 = factory.getGlyph(context3);
r.setCharacter(gly3);
System.out.println(r.getRow());
}
}
为了方便这届就写到main方法里面了,运行结果如图:
可以看出a创建了一次 ,a的大小12
,13是外部状态所以是外部传入,外部状态不能在享元内保存,而a字符是内部状态,行Row是有字符Character
组成,Row虽然实现了抽象享元接口,但是并没有再工厂中体现共享,因为他是不可共享的享元。
享元模式的角色有:
抽象享元(Flyweight)角色:是给实现享元提供的接口。
具体享元(ConcreteFlyweight)角色:实现抽象角色,此对象必须是共享的,所含的状态必须是内部状态。
不共享享元(UnSharedConcreteFlyweight)角色:此对象不可共享,不是所有实现抽象享元接口的的对象都要共享,此对象通常将ConcreteFlyweight作为组成元素。
享元工厂(FlyweightFactory)角色:负责创建和管理享元角色,确保合理共享。
客户端(Client)角色:维持一个Flyweight对象的引用,计算或存储一个(多个)外部存储状态。
享元模式的类图如下:
享元模式在java.lang.String设计上的使用,我们知道java中字符串始终保持共享一份,如下面代码片段:
String m = "a";
String n = "a";
System.out.println(m==n);
这样会输出true,说明m和n指向了同一个实例,内存中也只有一个"a"。这就是享元模式在String上的使用。
享元模式在文字编辑存贮过程中的使用,这里假定文章由行对象组成,行对象由若干个字符对象组成,但是如果每个字符都保存自己的对象,那么一篇文章成千上万个字符对象,这样严重消耗系统内存,造成不可接受的运行时开销,好的方法是利用享元模式,只保存ASCII字符编码值,作为内部不变的状态,对当个字符对象进行共享,而相对字符颜色、大小这样的格式化数据作为外部状态,由客户端维护,运行时由外部传入即可。每个行作为不可共享享元对象,它是由享元对象(字符对象)组合而成的。
举例代码如下:
抽象享元角色:
public interface Glyph {
public abstract void draw(Context context);
}具体享元角色:
public class Character implements Glyph{ private char c; private int size; @Override public void draw(Context context) { // TODO Auto-generated method stub this.size =context.getSize(); System.out.println(size+"号"+c+"被画出!"); } public Character(char c) { super(); this.c = c; System.out.println(c+"被创建!"); } public char getC() { return c; } public void setC(char c) { this.c = c; } }不共享享元角色:
public class Row implements Glyph {
private List<Character> list = new ArrayList<>();
@Override
public void draw(Context context) {
// TODO Auto-generated method stub
}
public Row() {
}
public void setCharacter(Glyph r) {
list.add((Character) r);
}
public int getSize() {
return list.size();
}
public String getRow() {
StringBuilder sb = new StringBuilder();
for (Character g : list) {
sb.append(g.getC());
}
return sb.toString();
}
}享元工厂角色:
public class GlyphFactory {
private Map<String, Glyph> map = new HashMap<>();
public Glyph getGlyph(Context context) {
String cStr = context.getC() + "";
Glyph gl = map.get(cStr);
if (gl == null) {
gl = new Character(context.getC());
map.put(cStr, gl);
}
gl.draw(context);
return gl;
}
}数据类:
public class Context {
private int size;
private char c;
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public char getC() {
return c;
}
public void setC(char c) {
this.c = c;
}
public Context(int size, char c) {
super();
this.size = size;
this.c = c;
}
}
客户端角色:
public class Client {
public static void main(String[] args) {
Row r = new Row();
GlyphFactory factory = new GlyphFactory();
Context context1 = new Context(12, 'a');
Glyph gly1 = factory.getGlyph(context1);
r.setCharacter(gly1);
Context context2 = new Context(13, 'a');
Glyph gly2 = factory.getGlyph(context2);
r.setCharacter(gly2);
Context context3 = new Context(13, 'b');
Glyph gly3 = factory.getGlyph(context3);
r.setCharacter(gly3);
System.out.println(r.getRow());
}
}
为了方便这届就写到main方法里面了,运行结果如图:
可以看出a创建了一次 ,a的大小12
,13是外部状态所以是外部传入,外部状态不能在享元内保存,而a字符是内部状态,行Row是有字符Character
组成,Row虽然实现了抽象享元接口,但是并没有再工厂中体现共享,因为他是不可共享的享元。
相关文章推荐
- 详解Java设计模式编程中的Flyweight享元模式的开发结构
- Java 设计模式之装饰模式的详解(结构模式)
- 详解java设计模式(七)之享元模式(结构型)
- Java设计模式之享元模式实例详解
- Java 设计模式之代理模式的详解(结构模式)
- C++设计模式编程之Flyweight享元模式结构详解
- JAVA设计模式(08):结构型-享元模式(Flyweight)
- 走穿23java种设计模式--12享元模式详解
- Java 设计模式之组合模式的详解(结构模式)
- Java开发中的23种设计模式详解(2)结构型
- Java开发中的23种设计模式详解----享元模式(Flyweight)
- java 设计模式之外观模式的详解(结构模式)
- Java与设计模式(二十一)结构型--享元模式
- Java 设计模式之桥接模式的详解(结构模式)
- Java 设计模式之适配器模式的详解(结构模式)
- 设计模式--结构模式--享元模式--Java
- 详解Java设计模式编程中命令模式的项目结构实现
- Java_23种经典设计模式详解
- Java中23种设计模式详解
- JAVA设计模式之享元模式