享元模式
一、完成者信息:
姓名:王智超
学号:07770120
二、模式信息
模式名称:享元模式
生活场景:考虑生产汽车的场景:一个品牌有各种型号的汽车,每种型号的汽车有相同的参数(如型号,长,宽,高),也有不同的参数(如颜色,马力) ,就可以把相同的参数拿出来共享。
终极目标:实现适应于扩充到对各种汽车和各种型号进行建模的情形。
1.不假思索的思路:通过给属性赋值的方法来做:没一辆车都有自己的所有的参数的属性。
类结构图:
代码浏览:
代码实现:
public class Car {
private String name;
private double width;
private double height;
private double length;
private String color;
private int power;
public Car(String name, double width, double height, double length, String color,int power) {
this.name = name;
this.width = width;
this.height = height;
this.length = length;
this.color = color;
this.power = power;
}
public void Produce() {
System.out.println("名称:" + name);
System.out.println("颜色:" + color);
System.out.println("马力:" + power);
System.out.println("宽度:" + width);
System.out.println("高度:" + height);
System.out.println("长度:" + length);
}
}
客户端调用:
public class BJSS {
public static void main(String[] args) {
Car BMWX5One = new Car("宝马X5",1.77,1.45,4.63,"银色",226);
BMWX5One.Produce();
Car BMWX5Two = new Car("宝马X5",1.77,1.45,4.63,"香槟色",238);
BMWX5Two.Produce();
}
}
存在问题:
1.重复代码会很多,相同的型号汽车有一部分参数是相同的;
2.类的结构过于复杂,难于维护;
3.最致命的一点是效率太差。生产大量汽车会创建大量的含有冗余数值的对象。
2.归纳阶段
当前目标:实现相同型号汽车的相同参数的提取,共享
思路:通过将数值不变的参数提取出来放在一个公共类中,再将须改变的参数放在另一个类中 ,公共类进行共享使用。
类结构图:
代码浏览:
代码实现:
public interface Flyweight {
public double getHeight();
public double getWidth();
public double getLength();
}
import java.util.HashMap;
public class FlyweightFactory {
private HashMap<String, Flyweight> hashMap;
static FlyweightFactory factory = new FlyweightFactory();
private FlyweightFactory() {
hashMap = new HashMap<String, Flyweight>();
}
public static FlyweightFactory getFactory() {
return factory;
}
public synchronized Flyweight getFlyweight(String key) {
if (hashMap.containsKey(key))
return hashMap.get(key);
else {
double width = 0, height = 0, length = 0;
String[] str = key.split("#");
width = Double.parseDouble(str[0]);
height = Double.parseDouble(str[1]);
length = Double.parseDouble(str[2]);
Flyweight ft = new ConcreteFlyweight(width, height, length);
hashMap.put(key, ft);
return ft;
}
}
class ConcreteFlyweight implements Flyweight { // ConcreteFlyweight是内部类
private double width;
private double height;
private double length;
private ConcreteFlyweight(double width, double height, double length) {
this.width = width;
this.height = height;
this.length = length;
}
public double getHeight() {
return height;
}
public double getWidth() {
return width;
}
public double getLength() {
return length;
}
}
}
public class Car {
Flyweight flyweight;
String name, color;
int power;
Car(Flyweight flyweight, String name, String color, int power) {
this.flyweight = flyweight;
this.name = name;
this.color = color;
this.power = power;
}
public void print() {
System.out.println("名称:" + name);
System.out.println("颜色:" + color);
System.out.println("马力:" + power);
System.out.println("宽度:" + flyweight.getWidth());
System.out.println("高度:" + flyweight.getHeight());
System.out.println("长度:" + flyweight.getLength());
}
}
客户端调用:
public class Application {
public static void main(String[] args) {
FlyweightFactory factory = FlyweightFactory.getFactory();
double width = 1.82, height = 1.47, length = 5.12;
String key = "" + width + "#" + height + "#" + length;
Flyweight flyweight = factory.getFlyweight(key);
Car BMWX6One = new Car(flyweight, "宝马X6", "黑色", 228);
Car BMWX6Two = new Car(flyweight, "宝马X6", "白色", 260);
BMWX6One.print();
BMWX6Two.print();
}
}
设计体会:
1.享元模式可以节省内存的开销,特别适合处理大量多属性的对象,这些对象的很多属性值是相同的。
2.享元模式可以只读取外部数据而不去影响内部共享的属性的数值,可以让共享类在不同的地方被调用。
3.验证阶段:
当前目标:添加一种汽车的共享属性
类结构图:
代码浏览:
代码实现:
public interface Flyweight {
public double getHeight();
public double getWidth();
public double getLength();
public String getStyle();
}
import java.util.HashMap;
public class FlyweightFactory {
private HashMap<String, Flyweight> hashMap;
static FlyweightFactory factory = new FlyweightFactory();
private FlyweightFactory() {
hashMap = new HashMap<String, Flyweight>();
}
public static FlyweightFactory getFactory() {
return factory;
}
public synchronized Flyweight getFlyweight(String key) {
if (hashMap.containsKey(key))
return hashMap.get(key);
else {
double width = 0, height = 0, length = 0;
String style = "";
String[] str = key.split("#");
width = Double.parseDouble(str[0]);
height = Double.parseDouble(str[1]);
length = Double.parseDouble(str[2]);
style = str[3];
Flyweight ft = new ConcreteFlyweight(width, height, length, style);
hashMap.put(key, ft);
return ft;
}
}
class ConcreteFlyweight implements Flyweight {
private double width;
private double height;
private double length;
private String style;
private ConcreteFlyweight(double width, double height, double length, String style) {
this.width = width;
this.height = height;
this.length = length;
this.style = style;
}
public double getHeight() {
return height;
}
public double getWidth() {
return width;
}
public double getLength() {
return length;
}
public String getStyle(){
return style;
}
}
}
public class Car {
Flyweight flyweight;
String name, color;
int power;
Car(Flyweight flyweight, String name, String color, int power) {
this.flyweight = flyweight;
this.name = name;
this.color = color;
this.power = power;
}
public void print() {
System.out.println("名称:" + name);
System.out.println("颜色:" + color);
System.out.println("马力:" + power);
System.out.println("宽度:" + flyweight.getWidth());
System.out.println("高度:" + flyweight.getHeight());
System.out.println("长度:" + flyweight.getLength());
System.out.println("外形:" + flyweight.getStyle());
}
}
客户端调用:
public class Application {
public static void main(String[] args) {
FlyweightFactory factory = FlyweightFactory.getFactory();
double width = 1.82, height = 1.47, length = 5.12;
String style = "SUV";
String key = "" + width + "#" + height + "#" + length + "#" + style;
Flyweight flyweight = factory.getFlyweight(key);
Car BMWX6One = new Car(flyweight, "宝马X6", "黑色", 228);
Car BMWX6Two = new Car(flyweight, "宝马X6", "白色", 260);
BMWX6One.print();
BMWX6Two.print();
}
}
验证结论:享元模式可以随时添加需要共享的属性,并且不需要非常大的改动代码。