一、享元模式
类似于线程池这一类,将使用的类缓存起来的方式就叫做享元模式。
二、使用步骤
1.示例
比方说我想实现买车,不同的车类型显示不同的价格
代码如下(示例):
抽象一个车类
public interface ICar {
void showMessage(String type);
}
车类
public class Car implements ICar{
private String name;
private int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public Car(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void showMessage(String type) {
price = new Random().nextInt(800);
System.out.println("名称为:"+name+"的,类型为:"+type+"的车售价"+price+"万元");
}
}
车场
public class CarFactory {
/**
* 和容器式单例的区别是在于,我不管你创建了几次,我的重点是重复利用
*/
private static Map<String,ICar> cars = new HashMap<String,ICar>();
public static ICar getCar(String name){
String key = name;
if(cars.containsKey(key)){
System.out.println("缓存");
return cars.get(key);
}else {
System.out.println("首次");
ICar car = new Car(name);
cars.put(key, car);
return car;
}
}
}
测试一下
咱们来看一下jdk中的运用看一下代码
String s1 = "hello";
String s2 ="he"+"llo";
String s3 = new String("hello");
String s4 = "he"+new String("llo");
String s5="he";
String s6="llo";
String s7=s5+s6;
System.out.println(s1==s2);
System.out.println(s1==s3);
System.out.println(s1==s4);
System.out.println(s1==s7);
System.out.println(s3==s4);
- s1==s2为true 原因就是String的常量池,其实就是一个享元模式。在编译阶段,jvm在常量池中加了一个对象s1,然后s2发现在常量池中有,所以是相等的。
- s1==s3为false 因为new了一个,在堆内存中开辟了一块内存,所以自然不相等。new 出了一个对象hello,然后常量池中放了一个hello,s3一共是两个对象。
- s1==s4 为false同上。但是s4有三个对象,he,new的llo,llo。
- s1==s7为false,因为s5和s6是变量,所以需要程序运行时才能计算,这样的话就跟 hello不是一个对象了。
再来看一个例子
Integer integer = Integer.valueOf(127);
Integer i=127;
Integer integer2 = Integer.valueOf(128);
Integer i2=128;
System.out.println(integer==i);//true
System.out.println(integer2==i2);//false
看一下源码
可以发现如果这个值在-128到127之间就从缓存中拿,否则new,这就是也是为啥超过了127就不相等
2.组合模式
组合模式,其实就是对多态的一种灵活运用,及所有类都会调用同一种方法来实现各自不同的功能。
场景:省市级 北京–朝阳区—亚运村
城市树抽象类
public abstract class CityTree {
public String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public CityTree(String name) {
this.name = name;
}
public void show(){};
}
省份类
public class Provice extends CityTree{
private List<CityTree> trees = new ArrayList<CityTree>();
private int level;
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
public Provice(String name,int level) {
super(name);
this.level = level;
}
public void show(){
System.out.println(this.name);
for (CityTree tree:trees) {
if(this.level!=0){
for (int j = 0; j < level; j++) {
System.out.print(" ");
}
for (int j = 0; j < level; j++) {
if(j==0){
System.out.print("+");
}
System.out.print("-");
}
}
tree.show();
}
}
public void add(CityTree ... cityTrees){
trees.addAll(Arrays.asList(cityTrees));
}
}
城市类
public class City extends CityTree{
public City(String name) {
super(name);
}
public void show() {
System.out.println(this.name);
}
}
测试一下
出来了,Spring中对此也有运用,例如SqlNode,他的实现类都会调用apply这个方法,是一条线。