一、作业题目及要求
使用 C# 编码(涉及类、接口、委托等关键知识点),实现对周黑鸭工厂的产品生产统一管理,主要产品包括鸭脖和鸭翅。武汉工厂能生生产鸭脖和鸭翅,南京工厂只能生产鸭翅,长沙工厂只能生产鸭脖。具体要求如下:
- 定义接口 IProductionFactory,包含生产鸭脖和鸭翅的方法。
- 定义类 WuhanFactory、NanjingFactory、ChangshaFactory 分别实现接口 IProductionFactory,用于具体的生产工厂。
- 使用委托 ProductionDelegate 定义生产委托。
- 在 Main 函数中,创建不同工厂的实例,并通过生产委托进行生产。
二、委托
(一)创建委托
delegate void ProductionDelegate(); //创建委托
通过ProductionDelegate
委托来引用各个工厂的生产方法(如ProduceNeck
和ProduceSwing
),使得我们可以在运行时决定具体调用哪个工厂的哪个生产方法。
(二)委托的作用
①传递参数
委托就像是一个“信使”,可以帮助我们传递方法作为参数,让其他方法去调用它。这样,当某个方法直接调用有困难时,委托就能帮我们轻松搞定啦。
②实现事件驱动编程和回调函数机制
委托还是实现事件驱动编程和回调函数机制的重要工具。它可以让我们的代码更加灵活和松耦合,方便我们管理和维护程序。
(三)添加委托
在主函数中,我们还可以向委托里添加方法,即使用+=运算符。下面代码为委托的调用列表“添加”了一个方法。
ProductionDelegate produceSwing = factory1.ProduceSwing; //生产鸭翅的委托
produceSwing += factory2.ProduceSwing;
produceSwing();
(四)使用委托时的注意事项
①明确要引用的方法的签名
定义委托类型时要明确它要引用的方法的签名,包括返回类型和参数列表。这样,委托才能正确地指向和调用相应的方法哦~
②确保安全性
使用委托时要确保它的安全性。不要将委托暴露给不信任的代码,以防止恶意代码篡改或滥用委托。
当委托被多个方法订阅时,要注意避免潜在的线程安全问题。如果多个线程可能同时修改委托的订阅列表或调用委托,那么就需要使用适当的同步机制来保证线程安全。
③及时取消订阅
当不再需要委托时,记得及时取消订阅,避免内存泄漏和不必要的资源消耗。
(五)意义
①将方法的调用与方法的实现解耦
委托是一种类型安全的函数指针,它允许我们将方法作为参数传递或赋值给变量。这样一来,我们就能够实现更灵活和可重用的代码,将方法的调用与方法的实现解耦,提高代码的模块化程度。
②可以轻松地实现事件通知和异步回调
委托是实现事件和回调机制的基础。通过委托,我们可以轻松地实现事件通知和异步回调,使得代码之间的交互更加灵活和高效。
③用于实现多播委托
委托还可以用于实现多播委托,即一个委托可以引用多个方法。这样,当委托被调用时,会依次执行所有被引用的方法,实现了一种观察者模式的效果。
总的来说,使用委托可以让我们编写更加灵活、可维护和可扩展的代码,提高代码的可重用性和可维护性
三、接口
(一)创建接口
创建制作鸭脖和鸭翅的方法。通过定义接口IproductionFactory,约束和定义所有工厂类必须实现的方法,其中包括生产鸭脖(ProduceNeck
)和生产鸭翅(ProduceSwing
)。
interface IProductionFactory //创建接口
{
void ProductSwing();
void ProductNeck();
}
(二)接口的作用
①实现代码的复用和扩展
接口定义了一种规范或契约,它规定了实现该接口的类必须提供哪些方法。这样,不同的类就可以通过实现相同的接口来具有相似的行为,从而实现代码的复用和扩展。
②实现多态性
接口可以帮助我们实现多态性。多态性意味着我们可以使用接口类型的变量来引用实现了该接口的任何类的实例。这样,我们就可以在运行时动态地决定调用哪个类的方法,从而实现更加灵活和可扩展的代码。
③解耦代码
接口还可以用来解耦代码,降低代码之间的耦合度。通过将依赖关系放在接口层,我们可以更容易地替换实现细节,而不需要修改大量的代码。
(三)意义
通过接口IProductionFactory,我们可以用同一接口引用来指向不同的实现类的实例(new WuhanFactory()、new NanjingFactory()、new ChangshaFactory(),在下文中会提到),而在调用ProduceNeck()和ProduceSwing()方法时,执行的却是各自类的具体实现,充分体现了多态性。
四、具体工厂类的实现
(一)注意事项
需要注意的是,哪怕南京工厂不生产鸭脖,长沙工厂不生产鸭翅,也需要在类里声明函数。每个工厂类里都需要用到接口里的函数,否则程序就会报错。实现接口中的方法时,必须保证返回类型、方法名、参数类型和参数顺序完全匹配。接口只能包含方法的声明,故实现接口的类需要自行提供所需的数据成员。
(二)具体代码示例
我们分别为武汉、南京和长沙工厂创建具体类,这些类通过实现前面定义的IProductionFactory
接口,提供了生产鸭脖和鸭翅的具体操作实现。其中,武汉工厂既生产鸭脖又生产鸭翅,南京工厂不生产鸭脖,长沙工厂不生产鸭翅。
class WuhanFactory : IProductionFactory
{
public void ProductSwing()
{
Console.WriteLine("武汉生产鸭翅");
}
public void ProductNeck()
{
Console.WriteLine("武汉生产鸭脖");
}
}
class NanjingFactory : IProductionFactory
{
public void ProductSwing()
{
Console.WriteLine("南京生产鸭翅");
}
public void ProductNeck()
{
Console.WriteLine("南京不生产鸭脖");
}
}
class ChangshaFactory : IProductionFactory
{
public void ProductNeck()
{
Console.WriteLine("长沙生产鸭脖");
}
public void ProductSwing()
{
Console.WriteLine("长沙不生产鸭翅");
}
}
五、使用委托实现生产的具体代码示例
using System;
delegate void ProductionDelegate(); //创建委托
interface IProductionFactory //创建接口
{
void ProduceSwing();
void ProduceNeck();
}
class WuhanFactory : IProductionFactory
{
public void ProduceSwing()
{
Console.WriteLine("武汉生产鸭翅");
}
public void ProduceNeck()
{
Console.WriteLine("武汉生产鸭脖");
}
}
class NanjingFactory : IProductionFactory
{
public void ProduceSwing()
{
Console.WriteLine("南京生产鸭翅");
}
public void ProduceNeck()
{
Console.WriteLine("南京不生产鸭脖");
}
}
class ChangshaFactory : IProductionFactory
{
public void ProduceSwing()
{
Console.WriteLine("长沙不生产鸭翅");
}
public void ProduceNeck()
{
Console.WriteLine("长沙生产鸭脖");
}
}
class Program
{
static void Main(string[] args)
{
WuhanFactory factory1 = new WuhanFactory(); //创建具体的工厂实例
NanjingFactory factory2 = new NanjingFactory();
ChangshaFactory factory3 = new ChangshaFactory();
ProductionDelegate produceSwing = factory1.ProduceSwing; //生产鸭翅的委托
produceSwing += factory2.ProduceSwing;
produceSwing();
ProductionDelegate produceNeck = factory1.ProduceNeck; //生产鸭脖的委托
produceNeck += factory3.ProduceNeck;
produceNeck();
}
}
六、总结
在这个案例中,我们通过c#设计了一套系统来实现对周黑鸭工厂产品生产的统一管理,其中涉及到定义接口、实现具体工厂类、使用委托以及各方法的协同工作。通过这种方式,系统的各个部分既保持了足够的灵活性和扩展性,又能够在统一的框架下高效协作,达成我们想要实现的目标。