Published on

设计模式(11)——享元 Flyweight

Authors
  • avatar
    Name
    Leon
    Twitter

十一、Flyweight(享元模式,对象结构型模式)

1. 意图:

  运用共享技术有效地支持大量细粒度的对象。

2. 适用:

  Flyweight 模式的有效性很大程度上取决于如何使用它以及在何处使用它。当以下情况都成立时使用 Flyweight 模式。

  1. 一个应用程序使用了大量的对象。
  2. 完全由于使用大量的对象,造成很大的存储开销。
  3. 对象的大多数状态都可变为外部状态。
  4. 如果删除对象的外部状态,那么可以用相对校少的共享对象取代很多组对象。
  5. 应用程序不依赖于对象标识。由于 Flyweight 对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

3. 类图:

4. 中间层思考:

  享元模式在系统和直接使用细粒度对象之间加入一个享元工厂,这个工厂就是中间层。系统不再直接创建和使用对象,而是由这个工厂来负责创建对象,工厂内部对同一对象只会创建一次,保证对象都是共享的。

5. Flyweight 与 简单工厂

  享元模式与简单工厂模式有点像,都用到了工厂的概念。其实享元模式里面就是用到了简单工厂模式来管理细粒度对象。享元模式解决的问题是对象的共享,而工厂模式解决的问题是如何封装对象的创建过程。明白它们两解决的问题,就知道它们是两种完全不一样的模式。但是它们却可以完美地结合在一起,协同解决问题。

6. C++实现:

  1. 先编写一个 Flyweight 类,构造函数接收一个参数 instrinsicState 用于描述内部状态(不变部分)
  2. 包含一个函数 Operation(const string& extrinsicState) 用于操作外部状态(可变部分)
  3. 编写 Flyweight 的子类 ConcreteFlyweight
  4. 编写工厂类 FlyweightFactory, 包含一个函数 GetFlyweight(const string& key), 一个 vector<Flyweight*> _fly 用于存储已创建的 Flyweight

Flyweight.h

// Flyweight.h
#pragma once

#include <string>
using namespace::std;

class Flyweight {
public:
	virtual ~Flyweight();
	virtual void Operation(const string& extrinsicState);
	string GetIntrinsicState();
protected:
	Flyweight(string intrinsicState);
private:
	string _intrinsicState;
};

class ConcreteFlyweight : public Flyweight {
public:
	ConcreteFlyweight(string intrinsicState);
	~ConcreteFlyweight();
	void Operation(const string& extrinsicState);
protected:
private:
};

Flyweight.cpp

//Flyweight.cpp
#include "Flyweight.h"
#include <iostream>
using namespace::std;

Flyweight::Flyweight(string intrinsicState) {
	this->_intrinsicState = intrinsicState;
}
Flyweight::~Flyweight() {}
void Flyweight::Operation(const string& extrinsicState){}
string Flyweight::GetIntrinsicState() {
	return this->_intrinsicState;
}

ConcreteFlyweight::ConcreteFlyweight(string intrinsicState) : Flyweight(intrinsicState) {
	cout << "ConcreteFlyweight Build..." << intrinsicState << endl;
}
ConcreteFlyweight::~ConcreteFlyweight() {}
void ConcreteFlyweight::Operation(const string& extrinsicState) {
	cout << "ConcreteFlyweight: 内蕴 [" << this->GetIntrinsicState() << "] 外蕴 [" << extrinsicState << "]" << endl;
}

FlyweightFactory.h

//FlyweightFactory.h
#pragma once
#include "Flyweight.h"
#include <string>
#include <vector>
using namespace::std;

class FlyweightFactory {
public:
	FlyweightFactory();
	~FlyweightFactory();
	Flyweight* GetFlyweight(const string& key);
protected:
private:
	vector<Flyweight*> _fly;
};

FlyweightFactory.cpp

//FlyweightFactory.cpp

#include "FlyweightFactory.h"
#include <iostream>
#include <string>
#include <cassert>
using namespace::std;

FlyweightFactory::FlyweightFactory() {}
FlyweightFactory::~FlyweightFactory() {}
Flyweight* FlyweightFactory::GetFlyweight(const string& key) {
	vector<Flyweight*>::iterator it = _fly.begin();
	for (; it != _fly.end(); it++) {
		//找到了,就一起用
		if ((*it)->GetIntrinsicState() == key) {
			cout << "already created by users..." << endl;
			return *it;
		}
	}

	Flyweight* fw = new ConcreteFlyweight(key);
	_fly.push_back(fw);
	return fw;
}

main.cpp

//main.cpp
#include "Flyweight.h"
#include "FlyweightFactory.h"
#include <iostream>
using namespace::std;

int main(int argc, char* argv[]) {
	FlyweightFactory* fc = new FlyweightFactory();
	Flyweight* fw1 = fc->GetFlyweight("hello");
	Flyweight* fw2 = fc->GetFlyweight("world!");
	Flyweight* fw3 = fc->GetFlyweight("hello");
	return 0;
}