前言:为什么要用享元模式
因为当一个系统中含有很多相似的对象时,如果每个对象都要占内存的话,那么对系统的性能是有影响的,此时如果将相似对象的共同部分作为一个共同的对象,不同的部分再通过方法传入不同的参数来实现的话,这样就能节省很多内存,代码如下:
一、单纯享元模式
1、抽象享元类
该类除了定义抽象方法用实现相似对象的共同功能,还要定义一个外部方法用于传入外部参数,从而组成不同的相似对象
abstract class AbstractCom//抽象享元类
{
protected abstract void Operation();//抽象方法,设置颜色
public void Display(Pos pos)//外部方法,并且要传入参数
{
this.Operation();
Console.WriteLine($"我的位置是x:{pos.X },y:{pos.Y }");
}
}
2、具体享元类
用于实现抽象享元类中的抽象方法
class BlackPiece : AbstractCom//具体享元类1
{
protected override void Operation()
{
Console.WriteLine("我是黑棋");
}
}
class WhitePiece : AbstractCom//具体享元类2
{
protected override void Operation()
{
Console.WriteLine("我是白棋");
}
}
3、外部参数,用于记录相似对象的不同部分
class Pos//外部参数
{
public int X { get; set; }
public int Y { get; set; }
}
4、工厂类
工厂类用于获取对象,根据键获取对象
class ComFactory//工厂类,创建唯一对象
{
private ComFactory()//防止实例化,只允许通过静态类获取唯一实例
{
}
private static ComFactory instance = new ComFactory();
Hashtable hashtable = new Hashtable();//存储享元对象
public static ComFactory GetInstance()
{
return instance;
}
public AbstractCom GetComObj(string key)//获取享元对象
{
if (hashtable.ContainsKey(key))//有对象就直接返回
{
return (AbstractCom)hashtable[key];
}
else//无对象,根据键来创建对象
{
if (key == "黑")
{
AbstractCom abstractCom = new BlackPiece();
hashtable.Add(key, abstractCom);
return abstractCom;
}
else if (key == "白")
{
AbstractCom abstractCom = new WhitePiece();
hashtable.Add(key, abstractCom);
return abstractCom;
}
else
{
return null;
}
}
}
}
调用:
ComFactory comFactory = ComFactory.GetInstance();
AbstractCom abstraction1 = comFactory.GetComObj("黑");
AbstractCom abstraction2 = comFactory.GetComObj("黑");
AbstractCom abstraction3 = comFactory.GetComObj("白");
AbstractCom abstraction4 = comFactory.GetComObj("白");
abstraction1.Display(new Pos() { X =10,Y =200});
abstraction2.Display(new Pos() { X = 0, Y = 0 });
abstraction3.Display(new Pos() { X = 0, Y = 0 });
abstraction4.Display(new Pos() { X = 0, Y = 0 });
Console.WriteLine($"{abstraction1 ==abstraction2}");
Console.WriteLine($"{abstraction3 == abstraction4}");
输出:
我是黑棋
我的位置是x:10,y:200
我是黑棋
我的位置是x:0,y:0
我是白棋
我的位置是x:0,y:0
我是白棋
我的位置是x:0,y:0
True
True
通过输出可以看出abstraction1和abstraction2 是同一个对象,abstraction3和abstraction4也是同一个对象,虽然他们通过外部参数实现了不同的功能,但是因为是同一个对象所以节省了内存。
二、复合享元模式:
abstract class AbstractCom//抽象享元类
{
public abstract void Add(AbstractCom abstractCom);
protected abstract void Operation();//抽象方法,设置颜色
public void Display()//外部方法,并且要传入参数
{
this.Operation();
}
}
class BlackPiece : AbstractCom//具体享元类1
{
protected override void Operation()
{
Console.WriteLine("我是黑棋");
}
public override void Add(AbstractCom abstractCom)
{
}
}
class WhitePiece : AbstractCom//具体享元类2
{
protected override void Operation()
{
Console.WriteLine("我是白棋");
}
public override void Add(AbstractCom abstractCom)
{
}
}
class PieceContainer:AbstractCom
{
List <AbstractCom> _List = new List<AbstractCom> ();
public override void Add(AbstractCom abstractCom)
{
_List.Add(abstractCom);
}
protected override void Operation()
{
Console.WriteLine("我是容器");
foreach (AbstractCom item in _List)
{
item.Display();
}
}
}
class ComFactory//工厂类,创建唯一对象
{
private ComFactory()//防止实例化,只允许通过静态类获取唯一实例
{
}
private static ComFactory instance = new ComFactory();
Hashtable hashtable = new Hashtable();//存储享元对象
public static ComFactory GetInstance()
{
return instance;
}
public AbstractCom GetComObj(string key)//获取享元对象
{
if (hashtable.ContainsKey(key))//有对象就直接返回
{
return (AbstractCom)hashtable[key];
}
else//无对象,根据键来创建对象
{
if (key == "黑")
{
AbstractCom abstractCom = new BlackPiece();
hashtable.Add(key, abstractCom);
return abstractCom;
}
else if (key == "白")
{
AbstractCom abstractCom = new WhitePiece();
hashtable.Add(key, abstractCom);
return abstractCom;
}
else
{
return null;
}
}
}
}
调用:
ComFactory comFactory = ComFactory.GetInstance();
AbstractCom abstraction1 = comFactory.GetComObj("黑");
AbstractCom abstraction2 = comFactory.GetComObj("黑");
AbstractCom container1 = new PieceContainer();
container1.Add(abstraction1);
container1.Add(abstraction2);
AbstractCom container2 = new PieceContainer();
AbstractCom abstraction3 = comFactory.GetComObj("白");
AbstractCom abstraction4 = comFactory.GetComObj("白");
container2.Add(abstraction3);
container2.Add(abstraction4);
container1.Add(container2);
container1.Display();