《设计模式》学习笔记(2)——工厂方法模式(Factory Method)
1、意图
定义一个用于创建对象的接口,让子类来决定实例化哪一个类。
2、别名
虚构造器。
3、适用性
在以下情况下使用此模式:
• 当一个类不知道它所必须创建的对象的类的时候。
• 当一个类希望由它的子类来指定它所创建的对象的时候。
• 当类将创建对象的职责委托给多个帮助子类中的某一个,且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
4、结构图示及注释
虚箭头表示一个类实例化另一个类的对象;三角形的表示继承关系。(后同)
Product:定义工厂方法所创建的对象的接口。
ConcreteProduct:实现Product所定义的接口。
Creator:声明工厂方法,它返回一个Product对象;或调用工厂方法以创建一个Product对象。
ConcreteCreator:重定义工厂方法以返回一个具体的ConcreteProduct实例。
5、实例代码
例子:在一款小游戏中我们定义了角色的两种职业:Warrior和Mage。但是在创建角色的时候,角色基类并不知道是应该去创建Warrior类还是Mage类,因此这里符合上面使用工厂方法模式的法则。
定义一个用于创建对象的接口,让子类来决定实例化哪一个类。
2、别名
虚构造器。
3、适用性
在以下情况下使用此模式:
• 当一个类不知道它所必须创建的对象的类的时候。
• 当一个类希望由它的子类来指定它所创建的对象的时候。
• 当类将创建对象的职责委托给多个帮助子类中的某一个,且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
4、结构图示及注释
虚箭头表示一个类实例化另一个类的对象;三角形的表示继承关系。(后同)
Product:定义工厂方法所创建的对象的接口。
ConcreteProduct:实现Product所定义的接口。
Creator:声明工厂方法,它返回一个Product对象;或调用工厂方法以创建一个Product对象。
ConcreteCreator:重定义工厂方法以返回一个具体的ConcreteProduct实例。
5、实例代码
例子:在一款小游戏中我们定义了角色的两种职业:Warrior和Mage。但是在创建角色的时候,角色基类并不知道是应该去创建Warrior类还是Mage类,因此这里符合上面使用工厂方法模式的法则。
using System;
/// <summary>
/// 角色基类。
/// </summary>
public abstract class Character
{
/// <summary>
/// 角色都可以实现跑的动作。
/// </summary>
public void Run()
{
Console.WriteLine("Yeeeeeeeah, me run!");
}
/// <summary>
/// 每个不同角色的技能都可能不同。
/// </summary>
public abstract void UseSkill();
}
/// <summary>
/// 创建战士角色。
/// </summary>
public class Warrior : Character
{
/// <summary>
/// 重写战士的技能。
/// </summary>
public override void UseSkill()
{
Console.WriteLine("My skill is heavy hit!");
}
}
/// <summary>
/// 创建魔法师角色。
/// </summary>
public class Mage : Character
{
/// <summary>
/// 重写魔法师的技能。
/// </summary>
public override void UseSkill()
{
Console.WriteLine("My skill is blizzard!");
}
}
/// <summary>
/// 定义角色工厂以创建不同角色。
/// </summary>
public abstract class CharacterFactory
{
public abstract Character CreateCharacter();
}
/// <summary>
/// 定义战士工厂以专门创建战士角色。
/// </summary>
public class WarriorFactory : CharacterFactory
{
public override Character CreateCharacter()
{
return new Warrior();
}
}
/// <summary>
/// 定义魔法师工厂以专门创建魔法师角色。
/// </summary>
public class MageFactory : CharacterFactory
{
public override Character CreateCharacter()
{
return new Mage();
}
}
public class Tester
{
public static void Main()
{
WarriorFactory warFactory = new WarriorFactory();
MageFactory mageFactory = new MageFactory();
Character myWarrior = warFactory.CreateCharacter();
Character myMage = mageFactory.CreateCharacter();
Console.WriteLine("-------------------------------------------------------");
Console.WriteLine("This is the warrior working:");
myWarrior.Run();
myWarrior.UseSkill();
Console.WriteLine();
Console.WriteLine("-------------------------------------------------------");
Console.WriteLine("This is the mage working:");
myMage.Run();
myMage.UseSkill();
}
}
/// <summary>
/// 角色基类。
/// </summary>
public abstract class Character
{
/// <summary>
/// 角色都可以实现跑的动作。
/// </summary>
public void Run()
{
Console.WriteLine("Yeeeeeeeah, me run!");
}
/// <summary>
/// 每个不同角色的技能都可能不同。
/// </summary>
public abstract void UseSkill();
}
/// <summary>
/// 创建战士角色。
/// </summary>
public class Warrior : Character
{
/// <summary>
/// 重写战士的技能。
/// </summary>
public override void UseSkill()
{
Console.WriteLine("My skill is heavy hit!");
}
}
/// <summary>
/// 创建魔法师角色。
/// </summary>
public class Mage : Character
{
/// <summary>
/// 重写魔法师的技能。
/// </summary>
public override void UseSkill()
{
Console.WriteLine("My skill is blizzard!");
}
}
/// <summary>
/// 定义角色工厂以创建不同角色。
/// </summary>
public abstract class CharacterFactory
{
public abstract Character CreateCharacter();
}
/// <summary>
/// 定义战士工厂以专门创建战士角色。
/// </summary>
public class WarriorFactory : CharacterFactory
{
public override Character CreateCharacter()
{
return new Warrior();
}
}
/// <summary>
/// 定义魔法师工厂以专门创建魔法师角色。
/// </summary>
public class MageFactory : CharacterFactory
{
public override Character CreateCharacter()
{
return new Mage();
}
}
public class Tester
{
public static void Main()
{
WarriorFactory warFactory = new WarriorFactory();
MageFactory mageFactory = new MageFactory();
Character myWarrior = warFactory.CreateCharacter();
Character myMage = mageFactory.CreateCharacter();
Console.WriteLine("-------------------------------------------------------");
Console.WriteLine("This is the warrior working:");
myWarrior.Run();
myWarrior.UseSkill();
Console.WriteLine();
Console.WriteLine("-------------------------------------------------------");
Console.WriteLine("This is the mage working:");
myMage.Run();
myMage.UseSkill();
}
}
6、关于工厂方法模式和简单工厂模式
简单工厂(Simple Factory)可以看作是参数化的工厂方法。由于简单工厂模式比较简单,就不再赘述了。
PS:说一点曾经我关于简单工厂和工厂方法的一个疑惑:由于最初是先看简单工厂,因此看工厂方法的时候觉得格外麻烦,总觉得工厂方法的做法是多此一举。直到参考了吕震宇的文章后才对为什么使用工厂方法模式有了一些了解。当然,上面的代码例子完全可以使用简单工厂来做,但是扩展性就受到了限制。比如我们现在需要新添加一个职业,那么就不得不去修改角色工厂;而使用工厂方法模式则只需新加一个角色类的子类以及角色工厂的子类即可。
由于初学,一些观点可能并不是很正确,欢迎各路高手指教。