【Java设计模式】· 享元模式 (Flyweight Pattern)

享元模式:


          1.今天这篇享元模式学习的时间比之前几个模式都长,看了好几篇他人的博客,最后用自己最简洁直白的话总结出来这篇文章。

 

          2.为什么我们要使用享元模式? 顾名思义,享元,就是共享一个"元",

             例如,我们打一篇英文的文章,大概200字,1000多个字母,我们并不需要创建1000个字母的对象,

             实际上我们由始至终只是在做一个26个字母的组合,我们仅创建了26个字母就完成的一篇文章,

             当我第一次敲下a后,后台(姑且叫做后台吧)会创建并存下了一个a,

             下一次我再需要使用a时,不需要再次创建一个a对象,只要从后台调用之前创建并存下的a。

             这就是享元模式——重复多次用到同一个元素,为了节省内存,那就共享!


【Java设计模式】· 享元模式 (Flyweight Pattern)_第1张图片


FlyweightFactory(工厂类):从里面获取需要的元素

Flyweight(享元抽象类):    不同类型的需共享的元素都是它的子类

ConcreteFlyweight,unsharedConcreteFlyweight(具体类): 具体的共享对象


          3.例子:假设我在写一封email,里面需要重复用到   不同颜色的字   和   不同大小的字   ,现在模拟这个过程。


Flyweight,例子中用到的颜色,字体小大都是它的子类/具体实现类

package pers.reus.model.flyweight;
/* *
 * Flyweight,享元模式的抽象类,当A类继承Flyweight类
 * 代表A类有可能是一个需要被重复使用多次的类
 * 所有A类才使用了享元模式
 * */
public abstract class Flyweight {
	public abstract void show();
}


Color 颜色类,通过它来设定字体颜色

package pers.reus.model.concreteFlyweight;

import pers.reus.model.flyweight.Flyweight;
//Color是Flyweight的concrete类
public class Color extends Flyweight{
	String color;
	
	//Color的构造函数需传入一个参数
	public Color(String color){
		this.color = color;
	}
	
	//展示这个Color类中被赋予的颜色
	public void show() {
		System.out.print("颜色: " + color);
	}

}



Font,字体大小类

package pers.reus.model.concreteFlyweight;

import pers.reus.model.flyweight.Flyweight;
//Font类是Flyweight的concrete类
public class Font extends Flyweight{
	String font;
	
	//Font的构造函数需传入一个参数
	public Font(String font){
		this.font = font;
	}
	
	//展示这个Font类中被赋予的字体大小值
	public void show() {
		System.out.println("      字体大小: " + font);	
	}

}



FlyweightFactory,工厂类,我们需要的 字体颜色 和 字体大小 都是从工厂类中获取,如果工厂类里面的hashtable没有存到有我们需要的,就会新建一个Color和Font对象来满足我们的需求,而下一次我们再有同样的请求的时候,hashtable就会有我们需要求 字体颜色 或 字体大小,不需要再重新新建对象。

package pers.reus.model.flyweightFactory;

import java.util.Hashtable;

import pers.reus.model.concreteFlyweight.Color;
import pers.reus.model.concreteFlyweight.Font;
import pers.reus.model.flyweight.Flyweight;

//FlyweightFactory享元模式工厂类
public class FlyweightFactory {
	//创建2个Hashtable分别用来存储  颜色  和  字体大小
	private Hashtable colorFlyweights = new Hashtable();
	private Hashtable fontFlyweights = new Hashtable();
	
	/* *
	 * getColorFlyweight作用是
	 * 当接收一个object对象
	 * 就会从color的hashtable里面找有没有这个对象
	 * 如果有就调用,没有就new Color()
	 * */
	public Flyweight getColorFlyweight(Object str) {
		//当接收一个值,先看看hashtable里面有没有
		Flyweight flyweight = (Flyweight) colorFlyweights.get(str);  
			//if 没有
			if(flyweight == null){
				//新建一个Color对象,并赋予它刚刚接收的值
				flyweight = new Color((String)str);  
				//把新的Color对象存到hashtable里面
				colorFlyweights.put(str, flyweight);  
			}
			return flyweight;
	}
	/* *
	 * getFontFlyweight作用是雷同的
	 * 为什么参数是Object str
	 * 因为Hashtable里面的参数是Object
	 * */
	public Flyweight getFontFlyweight(Object str) {	
		//以下的步骤和上面是一样的,做两个函数只是为了说明享元模式的扩展性
		Flyweight flyweight = (Flyweight) fontFlyweights.get(str);  
			if(flyweight == null){
				flyweight = new Font((String)str);  
				fontFlyweights.put(str, flyweight);  
			}
			return flyweight;
	}
	
	//返回两个Hashtable的长度
	public int getColorFlyweightSize(){  
			return colorFlyweights.size();  
	}
	public int getFontFlyweightSize(){  
			return fontFlyweights.size();  
    }

}



Client类的测试:

package pers.reus.model.client;

import pers.reus.model.flyweight.Flyweight;
import pers.reus.model.flyweightFactory.FlyweightFactory;

public class FlyweightPatternClient {

	public static void main(String[] args) {
		//创建工厂
		FlyweightFactory factory = new FlyweightFactory();   
		
		//c1~5表示5个颜色对象,f1~5表示5个字体对象
	    Flyweight c1,c2,c3,c4,c5;
	    Flyweight f1,f2,f3,f4,f5;
	    
	    //5次获取颜色对象
	  	c1 = factory.getColorFlyweight("蓝色"); 
	  	c2 = factory.getColorFlyweight("白色"); 
	  	c3 = factory.getColorFlyweight("绿色"); 
	  	c4 = factory.getColorFlyweight("白色"); 
	  	c5 = factory.getColorFlyweight("蓝色"); 
   	    
	  	//5次获取字体对象
	  	f1 = factory.getFontFlyweight("8px");
	  	f2 = factory.getFontFlyweight("18px");
	  	f3 = factory.getFontFlyweight("18px");
	  	f4 = factory.getFontFlyweight("8px");
	  	f5 = factory.getFontFlyweight("8px");
	  	
	  	//展示
	  	c1.show();
	  	f1.show();
	  	
	  	c2.show();
	  	f2.show();
	  	
	  	c3.show();
	  	f3.show();
	  	
	  	c4.show();
	  	f4.show();
	  	
	  	c5.show();
	  	f5.show();
	  	
	  	//显示颜色和字体一共创建了几个对象
	  	System.out.println("创建了 " + factory.getColorFlyweightSize() + " 个颜色对象");	
	  	System.out.println("创建了 " + factory.getFontFlyweightSize() + " 个字体对象");	
	}

}


测试结果:  可以看见分别向工厂类请求了5次字体颜色 和 5次字体小大,但是最后返回显示只创建了3个Color类,2个Font类,因为 "蓝白绿白蓝" 中,3个”蓝“享元一个Color类,Font也是同样的道理,Font的功能只是为了说明享元模式的易扩展性,可以扩展多个可共享的功能。

颜色: 蓝色      字体大小: 8px
颜色: 白色      字体大小: 18px
颜色: 绿色      字体大小: 18px
颜色: 白色      字体大小: 8px
颜色: 蓝色      字体大小: 8px
创建了 3 个颜色对象
创建了 2 个字体对象


        上几篇文章一直没说明:写博客是一个很好的检验过程,有些模式看着觉得懂了,但是实战时候却经常丢三落四地忘记小细节,而博客上也是用自己的语言去记录学习过程,可能有些自己能会心的字段别人却看不懂,希望大家多多支出,我是一只技术菜鸟,却有一颗成为大牛的心。


你可能感兴趣的:(设计模式)