在学习完大化设计模式之后,发现这本书编的真好,从一些通俗易懂的小故事,引入我们学习,今天就来学习一下设计模式中的“工厂三姐妹”
简单工厂模式:
这个模式是工厂三姐妹中唯一一个不属于设计模式的模式,因为它不符合“开放--封闭”原则,所以它只能称得上是一种编程习惯
举个栗子:
每次参加不同的聚会或者与不同的人见面,可能穿的衣服是不一样的,比如,你今天上午要与你的一个新客户见面,你可能会对你的老婆说:老婆,给拿件商务装(参数),我要去见我的一个客户,你老婆(工厂类)接到你的请求(商务装参数)后,从衣柜中取出一件商务装(具体产品),交给你。整个过程就完成了。
你可能根据不同的条件,要的衣服是不一样的,但要的衣服都是已经在你的衣柜中存在的。并且,每件上衣它们都属于同一种抽象,即它们可以从一个抽象类或接口中继承,这此衣服各自都有一定特征,这些都是条件。然后你要的时候,就可以向你老婆说一种特征,她就会根据这个特征为你服务了。这就是典型的简单工厂模式的应用。
代码:
namespace SimpleFactory
{
/// <summary>
/// 简单工厂模式中的核心部分:工厂类
/// </summary>
public class Factory
{
public ICoat CreateCoat(string styleName)
{
switch (styleName.Trim().ToLower())
{
case "business": //商务上衣
return new BusinessCoat();
case "fashion"://时尚上衣
return new FashionCoat();
default:
throw new Exception("还没有你要的那种衣服");
}
}
}
}
/// <summary>
/// 抽象产品类:上衣
/// </summary>
public interface ICoat
{
void GetYourCoat();
}
/// <summary>
/// 具体产品类:商务上衣
/// </summary>
public class BusinessCoat : ICoat
{
public void GetYourCoat()
{
Console.WriteLine("商务上衣");
}
}
/// <summary>
/// 具体产品类:时尚上衣
/// </summary>
public class FashionCoat : ICoat
{
public void GetYourCoat()
{
Console.WriteLine("时尚上衣");
}
}
简单工厂的缺点就是: 工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,这一点于
开闭原则是相违背的
但是简单工厂具有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例
简单工厂模式的UML图:
2.工厂方法:
工厂方法模式指的是定义一个创建对象的工厂接口,由其子类决定要实例化的类将实际工作推迟到子类中
定义一个工厂接口 :如何实现? 声明一个工厂抽象类
由其具体子类创建对象,创建派生于工厂抽象类,由具体工厂去创建具体产品,
既然需要创建具体产品,那么需要产品抽象类和具体产品类
简单工厂模式的缺点: 难以扩展,一旦添加新产品就不得不修改简单工厂方法
工厂模式之所以可以解决简单工厂的缺点,是因为他的实现把具体产品的穿件推迟到子类中,此时工厂类不再负责所有产品的创建
而只是给出具体工厂必须实现的接口
{
/// <summary>
/// 菜抽象类
/// </summary>
public abstract class Food
{
// 输出点了什么菜
public abstract void Print();
}
/// <summary>
/// 西红柿炒鸡蛋这道菜
/// </summary>
public class TomatoScrambledEggs : Food
{
public override void Print()
{
Console.WriteLine("西红柿炒蛋好了!");
}
}
/// <summary>
/// 土豆肉丝这道菜
/// </summary>
public class ShreddedPorkWithPotatoes : Food
{
public override void Print()
{
Console.WriteLine("土豆肉丝好了");
}
}
/// <summary>
/// 抽象工厂类
/// </summary>
public abstract class Creator
{
// 工厂方法
public abstract Food CreateFoddFactory();
}
/// <summary>
/// 西红柿炒蛋工厂类
/// </summary>
public class TomatoScrambledEggsFactory:Creator
{
/// <summary>
/// 负责创建西红柿炒蛋这道菜
/// </summary>
/// <returns></returns>
public override Food CreateFoddFactory()
{
return new TomatoScrambledEggs();
}
}
/// <summary>
/// 土豆肉丝工厂类
/// </summary>
public class ShreddedPorkWithPotatoesFactory:Creator
{
/// <summary>
/// 负责创建土豆肉丝这道菜
/// </summary>
/// <returns></returns>
public override Food CreateFoddFactory()
{
return new ShreddedPorkWithPotatoes();
}
}
/// <summary>
/// 客户端调用
/// </summary>
class Client
{
static void Main(string[] args)
{
// 初始化做菜的两个工厂()
Creator shreddedPorkWithPotatoesFactory = new ShreddedPorkWithPotatoesFactory();
Creator tomatoScrambledEggsFactory = new TomatoScrambledEggsFactory();
// 开始做西红柿炒蛋
Food tomatoScrambleEggs = tomatoScrambledEggsFactory.CreateFoddFactory();
tomatoScrambleEggs.Print();
//开始做土豆肉丝
Food shreddedPorkWithPotatoes = shreddedPorkWithPotatoesFactory.CreateFoddFactory();
shreddedPorkWithPotatoes.Print();
Console.Read();
}
}
}
所以这个时候如果系统需要添加新产品的时候,我们可以利用多态性来完成系统的扩展,
例如我还想多点一个 肉末茄子
那么我们就只需要定义一个肉末茄子具体工厂类,和肉末茄子类就可以了
/// <summary>
/// 肉末茄子这道菜
/// </summary>
public class MincedMeatEggplant : Food
{
/// <summary>
/// 重写抽象类中的方法
/// </summary>
public override void Print()
{
Console.WriteLine("肉末茄子好了");
}
}
/// <summary>
/// 肉末茄子工厂类,负责创建肉末茄子这道菜
/// </summary>
public class MincedMeatEggplantFactory : Creator
{
/// <summary>
/// 负责创建肉末茄子这道菜
/// </summary>
/// <returns></returns>
public override Food CreateFoddFactory()
{
return new MincedMeatEggplant();
}
}
/// <summary>
/// 客户端调用
/// </summary>
class Client
{
static void Main(string[] args)
{
// 如果客户又想点肉末茄子了
// 再另外初始化一个肉末茄子工厂
Creator minceMeatEggplantFactor = new MincedMeatEggplantFactory();
// 利用肉末茄子工厂来创建肉末茄子这道菜
Food minceMeatEggplant = minceMeatEggplantFactor.CreateFoddFactory();
minceMeatEggplant.Print();
Console.Read();
}
}
3.抽象工厂模式:
工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,工厂方法模式每个具体工厂类只完成单个实例的创建,所以它具有很好的可扩展性
但是在现实生活中,一个工厂只创建单个产品这样的例子很少,现在都是一个工厂创建一系列的产品,这个时候抽象工厂模式却可以很好的解决一系列产品创建的问题
/// <summary>
/// 下面以绝味鸭脖连锁店为例子演示下抽象工厂模式
/// 因为每个地方的喜欢的口味不一样,有些地方喜欢辣点的,有些地方喜欢吃不辣点
/// 客户端调用
/// </summary>
class Client
{
static void Main(string[] args)
{
// 南昌工厂制作南昌的鸭脖和鸭架
AbstractFactory nanChangFactory = new NanChangFactory();
YaBo nanChangYabo = nanChangFactory.CreateYaBo();
nanChangYabo.Print();
YaJia nanChangYajia= nanChangFactory.CreateYaJia();
nanChangYajia.Print();
// 上海工厂制作上海的鸭脖和鸭架
AbstractFactory shangHaiFactory = new ShangHaiFactory();
shangHaiFactory.CreateYaBo().Print();
shangHaiFactory.CreateYaJia().Print();
Console.Read();
}
}
/// <summary>
/// 抽象工厂类,提供创建两个不同地方的鸭架和鸭脖的接口
/// </summary>
public abstract class AbstractFactory
{
// 抽象工厂提供创建一系列产品的接口,这里作为例子,只给出了绝味中鸭脖和鸭架的创建接口
public abstract YaBo CreateYaBo();
public abstract YaJia CreateYaJia();
}
/// <summary>
/// 南昌绝味工厂负责制作南昌的鸭脖和鸭架
/// </summary>
public class NanChangFactory : AbstractFactory
{
// 制作南昌鸭脖
public override YaBo CreateYaBo()
{
return new NanChangYaBo();
}
// 制作南昌鸭架
public override YaJia CreateYaJia()
{
return new NanChangYaJia();
}
}
/// <summary>
/// 上海绝味工厂负责制作上海的鸭脖和鸭架
/// </summary>
public class ShangHaiFactory : AbstractFactory
{
// 制作上海鸭脖
public override YaBo CreateYaBo()
{
return new ShangHaiYaBo();
}
// 制作上海鸭架
public override YaJia CreateYaJia()
{
return new ShangHaiYaJia();
}
}
/// <summary>
/// 鸭脖抽象类,供每个地方的鸭脖类继承
/// </summary>
public abstract class YaBo
{
/// <summary>
/// 打印方法,用于输出信息
/// </summary>
public abstract void Print();
}
/// <summary>
/// 鸭架抽象类,供每个地方的鸭架类继承
/// </summary>
public abstract class YaJia
{
/// <summary>
/// 打印方法,用于输出信息
/// </summary>
public abstract void Print();
}
/// <summary>
/// 南昌的鸭脖类,因为江西人喜欢吃辣的,所以南昌的鸭脖稍微会比上海做的辣
/// </summary>
public class NanChangYaBo : YaBo
{
public override void Print()
{
Console.WriteLine("南昌的鸭脖");
}
}
/// <summary>
/// 上海的鸭脖没有南昌的鸭脖做的辣
/// </summary>
public class ShangHaiYaBo : YaBo
{
public override void Print()
{
Console.WriteLine("上海的鸭脖");
}
}
/// <summary>
/// 南昌的鸭架
/// </summary>
public class NanChangYaJia : YaJia
{
public override void Print()
{
Console.WriteLine("南昌的鸭架子");
}
}
/// <summary>
/// 上海的鸭架
/// </summary>
public class ShangHaiYaJia : YaJia
{
public override void Print()
{
Console.WriteLine("上海的鸭架子");
}
}