相关知识
泛型类型约束关键字 where(泛型类型约束) 泛型定义中的 where
子句指定对用作泛型类型、方法、委托或本地函数中类型参数的参数类型的约束。 约束可指定接口、基类或要求泛型类型为引用、值或非托管类型。
它们声明类型参数必须具备的功能。 例如,可以声明一个泛型类 FactoryClass,以使类型参数 T 实现 IProduct 产品接口:
1. public class FactoryClass<T> where T : IProduct { }
new 约束 new 约束指定泛型类声明中的类型实参必须有公共的无参数构造函数。 若要使用 new 约束,则该类型不能为抽象类型。
当泛型类创建类型的新实例时,请将 new 约束应用于类型参数,如下面的示例所示:
1. class Factory<T> where T : new()
2. {
3. public T CreateProduct()
4. {
5. return new T();
6. }
7. }
当与其他约束一起使用时,new() 约束必须最后指定,用逗号分隔区分:
1. class Factory<T> where T : IProduct,new()
2. {
3. public T CreateProduct()
4. {
5. return new T();
6. }
7. }
为什么要用工厂模式?
工厂模式的目的是为了实现解耦,将对象的创建和使用分开,即应用程序将对象的创建和初始化职责交给工厂对象。若一个对象A想要调用对象B时,如果直接通过new关键字来创建一个B实例,然后调用B实例,这样做的不好处是,当需求变更,要将B实例换成C实例时,则需要修改所有new了该实例的方法。
如何用工厂模式?
1.工厂族:一个工厂对应一类产品,多类产品则有多个工厂。
1.
interface IAbstractFactory //抽象工厂
2. {
3. IProduct CreatProduct();
4. }
1. interface IProduct //抽象产品
2. {
3. }
1. class ProductA:IProduct //产品A
2. {
3. public ProductA()
4. {
5. Console.WriteLine("产品A创建成功");
6. }
7. }
1. class ProductB:IProduct //产品B
2. {
3. public ProductB()
4. {
5. Console.WriteLine("产品B创建成功");
6. }
7. }
1. class FactoryA : IAbstractFactory ///产品A的工厂
2. {
3. public IProduct CreatProduct()
4. {
5. return new ProductA();
6. }
7. }
1. class FactoryB : IAbstractFactory ///产品B的工厂
2. {
3. public IProduct CreatProduct()
4. {
5. return new ProductB();
6. }
7. }
1. static void Main(string[] args)
2. {
3. //客户端调用
4. FactoryA factory1 = new FactoryA();
5. factory1.CreatProduct();//生产产品A
6. FactoryB factory2 = new FactoryB();
7. factory2.CreatProduct();//生产产品B
8. Console.ReadKey();
9. }
2.类的泛型:多类产品对应一个工厂。工厂类减少,但工厂对象还是没有减少
1.
public class Factory<T> where T : IProduct, new()//泛型工厂类
2. {
3. T CreateProduct()
4. {
5. T product = new T();
6. return product;
7. }
8. }
1. static void Main(string[] args)
2. {
3. //客户端调用
4. Factory<ProductA> factory1 = new Factory<ProductA>();
5. factory1.CreatProduct();//生产产品A
6. Factory<ProductB> factory2 = new Factory<ProductB>();
7. factory2.CreatProduct();//生产产品B
8. Console.ReadKey();
9. }
2.方法的泛型:多类产品对应一个工厂。工厂类减少,工厂对象减少
1. interface IAbstractFactory //抽象工厂
2. {
3. //泛型方法
4. public T CreatProduct<T>() where T:IProduct,new();
5. }
1. class Factory : IAbstractFactory ///所有产品的工厂
2. {
3. public T CreatProduct<T>() where T:IProduct,new()
4. {
5. return new T();
6. }
7. }
1. static void Main(string[] args)
2. {
3. //客户端调用
4. Factory factory = new Factory();
5. factory.CreatProduct<ProductA>();//生产产品A
6. factory.CreatProduct<ProductB>();//生产产品B
7. Console.ReadKey();
8. }
任务要求
在植物大战僵尸的游戏中,每关关卡总是会有很多僵尸发动攻击。请阅读右侧仿真源码,使用工厂模式来设计僵尸生产的类。 输入格式:
输入第一行给出一个正整数n(n⩽3)表示生产僵尸的批次。随后n行,每行给出2个整数,作为僵尸的类型和数量,其间以半角逗号分隔。(1代表普通僵尸,2代表铁桶僵尸,3代表巨人僵尸)
输出格式: 在多行内输出僵尸创建成功的输出语句。
输入样例: 3
1,3
2,2
3,1 输出样例:
普通僵尸准备发动攻击
普通僵尸准备发动攻击
普通僵尸准备发动攻击
铁桶僵尸准备发动攻击
铁桶僵尸准备发动攻击
巨人僵尸准备发动攻击
代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace F1
{
public interface IZombie
{
}
public class generalZombie : IZombie
{
public generalZombie()
{
Console.WriteLine("普通僵尸准备发动攻击");
}
}
public class bucketZombie : IZombie
{
public bucketZombie()
{
Console.WriteLine("铁桶僵尸准备发动攻击");
}
}
public class giantZombie : IZombie
{
public giantZombie()
{
Console.WriteLine("巨人僵尸准备发动攻击");
}
}
public class ZombieFactory ///所有僵尸的工厂
{
/********** Begin *********/
//实现CreatZombie泛型方法(创建任意类型的僵尸)
public T CreatZombie<T>() where T : IZombie, new()
{
return new T();
}
/********** End *********/
}
class Program
{
static void Main(string[] args)
{
/********** Begin *********/
int n = Convert.ToInt32(Console.ReadLine());
ZombieFactory factory = new ZombieFactory();
for (int i = 0; i < n; i++)
{
string type = Console.ReadLine();
string[] num = type.Split(',');
int t = int.Parse(num[0]);
int m=int.Parse(num[1]);
switch (t)
{
case 1:
for (int j = 0; j < m; j++)
{
factory.CreatZombie<generalZombie>();
}
break;
case 2:
for (int j = 0; j < m; j++)
{
factory.CreatZombie<bucketZombie>();
}
break;
case 3:
for (int j = 0; j < m; j++)
{
factory.CreatZombie<giantZombie>();
}
break;
case 0:
default:
Console.WriteLine("重新输入");
break;
}
/********** End *********/
}
}
}
}
main方法的内容可以做些修改,不过方法大同小异
int n=Int32.Parse(Console.ReadLine());
ZombieFactory zombieFactory = new ZombieFactory();
for (int i = 0; i < n; i++)
{
string str = Console.ReadLine();
string[] a = str.Split(',');
int[] a1 = Array.ConvertAll<string, int>(a,int.Parse);
if (a1[0] == 1) {
for (int j = 0; j < a1[1]; j++)
{
zombieFactory.CreatZombie<generalZombie>();
}
}
if (a1[0] == 2)
{
for (int j = 0; j < a1[1]; j++)
{
zombieFactory.CreatZombie<bucketZombie>();
}
}
if (a1[0] == 3)
{
for (int j = 0; j < a1[1]; j++)
{
zombieFactory.CreatZombie<giantZombie>();
}
}
}