亨元模式据说很适合解决因创建大量对象而引起的性能问题。这个模式比较负责且作用是提高性能,所以使用情况并不多。
亨元的结构
亨元模式目的是减少对象数量,所以得把对象内部状态抽象为 * 内部数据* 和 外部数据,通过共享 内部数据来减少对象。而且需要工厂模式来实例化这些由 内部数据 抽象出来的共享对象。
Demo 1:汽车登记
假设要开发一个系统,用以代表一个城市的所有汽车。
传统做法可能是像这样:
<!--lang: JavaScript-->
var Car = function (make, model, year, owner, tag, renewDate) {
this.make = make;
this.model = model;
//............
this.renewDate = renewDate;
};
Car.prototype = {
getMak: function () {//...},
getModel: function () {//...},
getYear: function () {//...},
transferOwnership: function (newOwner, newTag, newRenewDate) {
this.owner = newOwner;
this.tag = newTag;
this.renewDate = newRenewDate;
},
renewRegistration: function (newRenewDate) {//...}
}
起初这个系统肯定表现不错,但随着汽车越来越多,系统的内存大量被用于存储汽车对象,系统会越来越慢
划分内在状态和外在状态
划分存在着一定的随意性,既要保持对象的模块性,又要把尽可能多的数据划到 外部数据里。这个Demo中把车的内在属性划分为内在数据,所有权信息划分为外在数据
亨元模式的代码:
var Car = function (make, model, year) {
//......
}
Car.prototype = {
getMak: function () {//...},
getModel: function () {//...},
getYear: function () {//...},
}
var CarFactory = (function () {
var cars = {};
return {
createCar: function (make, model, year) {
if (cars[make + '-' + model + '-' + year]) {
return cars[make + '-' + model + '-' + year];
}
var car = new Car(make, model, year);
cars[make + '-' + model + '-' + year] = car;
return car;
}
}
})();
var CarRecodeManager = (function () {
var carRecordDatabase = {};
return {
addCarRecord: function (make, model, year, tag, owner, renewDate) {
var car = CarFactory.createCar(make, model, year);
carRecordDatabase[tag] = {
owner: owner,
renewDate: renewDate,
car: car
};
},
transferOwnership: function (tag, newOwner, newTag, newRenewDate) {
var record = carRecordDatabase[tag];
record .owner = newOwner;
record .tag = newTag;
record .renewDate = newRenewDate;
},
//other function .......
}
})()
上面是用亨元模式重构后的系统。Car对象为抽象内部数据后的对象,CarFactory用于实例化对象,CarRecordeManager用于管理保存外部数据。 可以看出亨元模式比较复杂,把原来简单的一个类分为了一个类 + 两个单体。但是亨元模式确实额可以大幅度减少对象的创建,从而提高性能。
管理外在状态
管理亨元对象的外在状态有许多不同的方法,常见方法就是像上个Demo那样用一个管理器对象,还有一种方法是用组合模式自身的层次体系来保存外在状态。 组个对象的结构本身可以包含外部数据,叶对象通常只包含极少的内部数据,所以很容易转化为亨元模式。
亨元模式的一般步骤
- 将所有外在数据从目标类剥离。
- 创建一个管理该类的实例的工厂。
- 创建一个保存外部数据的管理器对象。