一、完成者信息:
姓名:王智超
学号:07770120
二、模式信息
模式名称:享元模式
生活场景:考虑生产汽车的场景:一个品牌有各种型号的汽车,每种型号的汽车有相同的参数(如型号,长,宽,高),也有不同的参数(如颜色,马力) ,就可以把相同的参数拿出来共享。
终极目标:实现适应于扩充到对各种汽车和各种型号进行建模的情形。
1.不假思索的思路:通过给属性赋值的方法来做:没一辆车都有自己的所有的参数的属性。
类结构图:
代码浏览:
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 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 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 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 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 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();
}
}
验证结论:享元模式可以随时添加需要共享的属性,并且不需要非常大的改动代码。