一、应用场景
需求:要建立PC版电商网站、小程序版的电商网站、App版的电商网站。
措施:将代码复制粘贴,根据用户的不同需求,定制化的进行修改、开发。
存在问题:
- 针对每个用户的网站,都需要创建新的服务器资源,数据库资源,造成资源浪费;
- 代码迭代的成本巨大。
解决方案:
- 整合到一个网站中,共享其相关的代码和数据,对于硬件资源可以大大减小使用量;
- 对于代码,由于核心的代码和数据都是共享同一份实例,提高啦代码的维护性和扩展性。
总结:当系统中大量使用某些相同或者相似的对象,这些对象会消耗大量的资源,并且这些对象剔除外部状态后都可以通过同一个对象来替代,这时,我们可以使用享元设计模式来解决。
享元和单例模式的区别:以共享单车为例,如果是单例模式,一座城市就只有一辆小黄车。享元模式是一座城市投放几万量小黄车供几千万人使用,避免资源的浪费。
- 内部状态:对象内部不受环境改变的部分作为内部状态;如上传视频的内容。
- 外部状态,随着环境的变化而变化的部分。如上传视频的用户、视频的名称
享元模式运用共享技术有效的支持大量细粒度的对象;
享元模式有池的概念,单例没有。
享元模式有内部状态、外部状态之分,单例没有。
享元模式的uml图如下:
- Flyweight是抽象享元角色。它是产品的抽象类,同时定义出对象的外部状态和内部状态(外部状态及内部状态相关内容见后方)的接口或实现;
- ConcreteFlyweight是具体享元角色,是具体的产品类,实现抽象角色定义的业务;
- UnsharedConcreteFlyweight是不可共享的享元角色,一般不会出现在享元工厂中;
- FlyweightFactory是享元工厂,它用于构造一个池容器,同时提供从池中获得对象的方法。
二、代码
代码语言:javascript复制 public abstract class FlyWeightBike
{
//内部状态:BikeID、State(1表示骑行中,0表示使用中)、
//外部状态:骑车子的用户
//方法:骑行、锁车
public string BikeID { get; set; }
public int State { get; set; }
public abstract void Ride(string userName);
public abstract void Back(string userName);
}
public class YellowBike : FlyWeightBike
{
public YellowBike(string id)
{
this.BikeID = id;
}
public override void Back(string userName)
{
this.State = 0;
Console.WriteLine("用户" userName "正在归还,ID是" this.BikeID "的自行车");
}
public override void Ride(string userName)
{
this.State=1;
Console.WriteLine("用户" userName "正在骑行,ID是" this.BikeID "的自行车");
}
}
public class BikeFactory
{
List<FlyWeightBike> bikePool = new List<FlyWeightBike>();
public BikeFactory()
{
for (int i = 0; i < 3; i )
{
bikePool.Add(new YellowBike(i.ToString()));
}
}
public FlyWeightBike GetBike()
{
for (int i = 0; i < bikePool.Count; i )
{
if (bikePool[i].State==0)
{
return bikePool[i];
}
}
return null;
}
}
代码语言:javascript复制 BikeFactory bikeFactory = new BikeFactory();
FlyWeightBike flyWeightBike= bikeFactory.GetBike();
flyWeightBike.Ride("张三");
flyWeightBike.Back("张三");
FlyWeightBike flyWeightBike1 = bikeFactory.GetBike();
flyWeightBike1.Ride("李四");
FlyWeightBike flyWeightBike2 = bikeFactory.GetBike();
flyWeightBike2.Ride("王五");