23种设计模式-12-享元模式

/// <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();
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值