优点:减少内存中对象的数量,相同或相似对象在内存中只存在一个,节省内存,提高系统性能。
缺点:运行时间变长,用时间换取内存。
享元模式能做到共享的关键是区分了内部状态和外部状态。
内部状态:可以共享,不会随着环境变化而改变。
外部状态:不可用共享,会随着环境变化而改变。
主要分为四个角色:
- Flyweight: 抽象享元类。一个接口或者抽象类,声明公共方法,这些方法可以向外部提供对象内部状态和设置对象的外部状态。
- ConcreteFlyweight: 具体享元类。为内部状态提供成员变量进行存储。
- UnsharedConcreteFlyweight: 非共享享元类。不能被共享的子类,可以设计为非共享享元类。
- FlyweightFactory: 享元工厂类。创建并管理享元对象,享元池一般设置成键值对。
例子:比如五子棋中的黑棋或白棋,它们颜色形状都是一样的,可以共享,不会随着环境的变化而改变,这就是内部状态。唯一不一样的就是它们的坐标,不可共享,因为每块棋子的坐标都是不一样的,这就是外部状态。
把外部状态独立出来(UnsharedConcreteFlyweight):
/**
* 这是一个坐标类。
* UnsharedConcreteFlyweight: 非共享享元类。不能被共享的子类,可以设计为非共享享元类。
*/
public class CoordinateUnshared {
private int x, y;
public CoordinateUnshared(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
Flyweight: 抽象享元类。一个接口或者抽象类,声明公共方法,这些方法可以向外部提供对象内部状态和设置对象的外部状态:
/**
* 这是一个棋子抽象享元类
* Flyweight: 抽象享元类。一个接口或者抽象类,声明公共方法,这些方法可以向外部提供对象内部状态和设置对象的外部状态。
*/
public interface ChessFlyweight {
void setColor(String color);
String getColor();
void displayPosition(CoordinateUnshared c);
}
ConcreteFlyweight: 具体享元类。为内部状态提供成员变量进行存储:
/**
* 这是一个具体享元类
* ConcreteFlyweight: 具体享元类。为内部状态提供成员变量进行存储。
*/
public class ChessConcrete implements ChessFlyweight {
private String color;
public ChessConcrete(String color) {
this.color = color;
}
@Override
public void setColor(String color) {
this.color = color;
}
@Override
public String getColor() {
return color;
}
@Override
public void displayPosition(CoordinateUnshared c) {
Log.d("TAG", "对象:" + this + "\n颜色:" + color + "\n棋子位置:" + "x = " + c.getX() + " y = " + c.getY());
}
}
FlyweightFactory: 享元工厂类:
import java.util.HashMap;
import java.util.Map;
/**
* FlyweightFactory: 享元工厂类。创建并管理享元对象,享元池一般设置成键值对。
*/
public class ChessFlyweightFactory {
private static Map<String, ChessFlyweight> map = new HashMap<String, ChessFlyweight>();
public static ChessFlyweight getChess(String color) {
if (map.get(color) != null) {
return map.get(color);
} else {
ChessFlyweight chessFlyweight = new ChessConcrete(color);
map.put(color, chessFlyweight);
return chessFlyweight;
}
}
}
调用:
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
/**
* 这是调用者
*/
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ChessFlyweight chessFlyweight1 = ChessFlyweightFactory.getChess("黑色");
ChessFlyweight chessFlyweight2 = ChessFlyweightFactory.getChess("黑色");
ChessFlyweight chessFlyweight3 = ChessFlyweightFactory.getChess("白色");
Log.d("TAG", "添加外部处理-----------------------");
chessFlyweight1.displayPosition(new CoordinateUnshared(10, 10));
chessFlyweight2.displayPosition(new CoordinateUnshared(20, 20));
chessFlyweight3.displayPosition(new CoordinateUnshared(30, 30));
}
}
结果:
image.png
创建了两次黑色棋子,但是并没有生成新对象,而是同一个对象,只是添加的外部处理不一样(坐标),白色棋子为新对象,因为系统中还不存在白色对象,所以无论创建多少黑色对象和白色对象,黑色和白色也都各只存在一个。
已完成测试!有不对的地方欢迎指出,感恩。
网友评论