/// <summary>
/// 车:内部状态
/// </summary>
public class Car
{
public Car(string color)
{
this.Color = color;
Console.WriteLine("Car被实例化,color = " + color);
}
public string Color { get; set; }
public void Drive(Driver driver)
{
Console.WriteLine("{0}在开{1}的车!", driver.Name, Color);
}
}
/// <summary>
/// 司机:外部状态
/// </summary>
public class Driver
{
public Driver(string name)
{
this.Name = name;
}
public string Name { get; set; }
}
/// <summary>
/// 享元工厂:类似于车库
/// </summary>
public class FlyweightFactory
{
/// <summary>
/// 这里真实场景需要考虑到现场安全问题
/// 解决办法:1.lock;2.线程安全数据类型:ConcurrentDictionary;3.原子操作
/// 这里的Dictionary,在java里面相当于map,java开发者可以这样理解
/// 我这里使用lock,因为lock在C#和java都有,方便大家理解
/// </summary>
private Dictionary<string, Car> CarContainer = new Dictionary<string, Car>();
/// <summary>
/// 我这里使用lock防止并发,因为lock在C#和java都有,方便大家理解
/// readonly关键字此时相当于java的final关键字
/// </summary>
private static readonly object CarLocker = new object();
public FlyweightFactory()
{
//最开始家里有两辆车,一辆白色,一辆黑色
this.CarContainer.Add("白色", new Car("白色"));
this.CarContainer.Add("黑色", new Car("黑色"));
}
/// <summary>
/// 从车库取车操作
/// </summary>
/// <returns></returns>
public Car GetCar(string color)
{
Car car = null;
CoreService.RunLock(CarLocker, () =>
{
//判断车库里面有没有这个颜色的车
if (CarContainer.ContainsKey(color))
{
Console.WriteLine("车库里有{0}的车,直接从车库取走", color);
//有这个颜色的就直接取车
car = CarContainer[color];
}
else
{
Console.WriteLine("车库里没有{0}的车,去买一辆放在车库,然后取走", color);
//没有的话,就买一辆新的,放在车库
CarContainer.Add(color, new Car(color));
//然后取出去,下次就不用买了,可以直接取
car = CarContainer[color];
}
});
return car;
}
}
class Program
{
/// <summary>
/// 享元模式:
/// 如果我们需要大量相同的对象,如果一个个去new的话,会导致很浪费资源和性能,而享元就是为了解决这个问题的
/// 看到这里,大家脑海里肯定会想:哎,这不是原型模式吗?怎么享元模式跟原型模式一样了?
///
/// 让我来解释一下吧:
/// 原型模式:为了避免new,而采用克隆的方式来构造对象(注重构造),原型模式是一个创建型模式,所以注重的是创建
/// 享元模式:不仅仅是为了避免new,更多的还是为了重用一个对象(注重重用),它的一些属性我们是可以直接用的。
///
/// 此文中的例子:大头儿子一家
/// 假如大头儿子一家三口,家里有两辆车,一辆白色,一辆黑色,然后家里每次出行时需要开车
/// 不可能说每一次出行都要去新买一辆车吧(new),所以只需要买一个(new一次),之后要使用,直接去车库开就好了
/// 如果家里的车不够了,假如大头儿子长大了,想要买一辆蓝色的车,此时车库里没有,则需要重新去买一辆放在车库里
/// 以后大头儿子要开车的话就可以从车库里去开了
///
/// 享元模式又分为:1.内部状态;2.外部状态;
/// 内部状态:在享元的内部不会因为环境的改变而改变,在上述例子中车就是内部状态,只要买了就在车库,不会改变
/// 外部状态:会随环境改变而改变,不可以享元的状态,在上述例子中大头儿子一家就是外部状态,车不会变,但是谁开车,这个是会变化的,这个无法享元
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
//不管取多少遍车,同一个颜色的车,永远只会实例化一次(买一次)
FlyweightFactory carFactory = new FlyweightFactory();
Car car1 = carFactory.GetCar("白色");
Car car2 = carFactory.GetCar("黑色");
Car car3 = carFactory.GetCar("蓝色");
carFactory.GetCar("白色");
carFactory.GetCar("黑色");
carFactory.GetCar("蓝色");
//指定外部环境(谁去开车)
car1.Drive(new Driver("围裙妈妈"));
car2.Drive(new Driver("小头爸爸"));
car3.Drive(new Driver("大头儿子"));
Console.WriteLine("End");
Console.ReadKey();
}
}