(原创)无废话C#设计模式之五:Prototype

无废话C#设计模式之五:Prototype

意图

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

场景

游戏场景中的有很多相似的敌人,它们的技能都一样,但是随着敌人出现的位置不同,这些人的能力不太一样。假设,我们现在需要把三个步兵组成一队,其中还有一个精英步兵,能力特别高。那么,你或许可以创建一个敌人抽象类,然后对于不同能力的步兵创建不同的子类。然后,使用工厂方法等设计模式让调用方依赖敌人抽象类。

问题来了,如果有无数种能力不同步兵,难道需要创建无数子类吗?还有,步兵模型的初始化工作是非常耗时的,创建这么多步兵对象可能还会浪费很多时间。我们是不是可以通过只创建一个步兵原型,然后复制出多个一摸一样的步兵呢?复制后,只需要调整一下这些对象在地图上出现的位置,或者调整一下它们的能力即可。原型模式就是用来解决这个问题的。

示例代码

using System;

using System.Threading;

using System.Collections.Generic;

using System.IO;

using System.Runtime.Serialization.Formatters.Binary;

using System.Diagnostics;

namespace PrototypeExample

{

class Program

{

static void Main(string[] args)

{

Stopwatch sw = new Stopwatch();

sw.Start();

Enemy enemyPrototype = new FootMan(5, 4, new Location(100, 200));

GameScene gs = new GameScene();

List<Enemy> enemyGroup = gs.CreateEnemyGroup(enemyPrototype);

foreach (FootMan ft in enemyGroup)

{

ft.ShowInfo();

ft.FootmanAttack();

}

Console.WriteLine(sw.ElapsedMilliseconds);

}

}

class GameScene

{

public List<Enemy> CreateEnemyGroup(Enemy enemyPrototype)

{

List<Enemy> enemyGroup = new List<Enemy>();

Enemy e1 = enemyPrototype.Clone(true);

e1.Location.x = enemyPrototype.Location.x - 10;

Enemy e2 = enemyPrototype.Clone(true);

e2.Location.x = enemyPrototype.Location.x + 10;

Enemy elite = enemyPrototype.Clone(true);

elite.Power = enemyPrototype.Power * 2;

elite.Speed = enemyPrototype.Speed * 2;

elite.Location.x = enemyPrototype.Location.x;

elite.Location.y = enemyPrototype.Location.y + 10;

enemyGroup.Add(e1);

enemyGroup.Add(e2);

enemyGroup.Add(elite);

return enemyGroup;

}

}

[Serializable]

class Location

{

public int x;

public int y;

public Location(int x, int y)

{

this.x = x;

this.y = y;

}

}

[Serializable]

abstract class Enemy

{

protected Location location;

public Location Location

{

get { return location; }

set { location = value; }

}

protected int power;

public int Power

{

get { return power; }

set { power = value; }

}

protected int speed;

public int Speed

{

get { return speed; }

set { speed = value; }

}

public abstract Enemy Clone(bool isDeepCopy);

public abstract void ShowInfo();

public Enemy(int power, int speed, Location location)

{

Thread.Sleep(1000); // Construct method is assumed to be a high calc work.

this.power = power;

this.speed = speed;

this.location = location;

}

}

[Serializable]

class FootMan : Enemy

{

private string model;

public FootMan(int power, int speed, Location location)

: base(power, speed, location)

{

model = "footman";

}

public override void ShowInfo()

{

Console.WriteLine("model:{0} power:{1} speed:{2} location:({3},{4})", model, power, speed, location.x, location.y);

}

public override Enemy Clone(bool isDeepCopy)

{

FootMan footman;

if (isDeepCopy)

{

MemoryStream memoryStream = new MemoryStream();

BinaryFormatter formatter = new BinaryFormatter();

formatter.Serialize(memoryStream, this);

memoryStream.Position = 0;

footman = (FootMan)formatter.Deserialize(memoryStream);

}

else

footman = (FootMan)this.MemberwiseClone();

return footman;

}

public void FootmanAttack()

{

Console.WriteLine("FootmanAttack");

}

}

}

代码执行结果如下图:

代码说明

l Enemy类是抽象原型,它有两个用途,一是定义了原型的一些抽象内容,二是定义了原型模式必须的拷贝方法。在这里,我们看到,每个敌人的属性有位置、攻击力、速度等,并且能通过ShowInfo()方法来获取这个人的信息。

l FootMan类就是具体原型了,它显示了敌人的具体参数以及实现了克隆自身。

l GameScene类就是调用方,在这里我们并没有看到有和具体原因进行依赖,通过复制传入的克隆原型,得到一些新的敌人,在原型的基础上稍微调整一下就变成了一支敌人部队。

l 原型模式通过对原型进行克隆来替代无数子类,因此也就减少了调用方和具体类型产生依赖的程序。

l Clone()方法接受一个参数,表示是否是深拷贝。在这里,我们通过序列化反序列化实现深拷贝,深拷贝实现对象的完整复制,包括对象

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值