工厂模式的剖析和延伸

一、罗嗦几句

几个月前面试的时候,我还谈论过自己使用过抽象工厂模式,以及其应用场景,面试官只是莞尔一笑。现在回想起来,模式似乎只是一种方法而已,其根本目的还是为了规范和方便代码开发,没有必要去执着于哪种模式,只要能更好的实现我们的目的,那么你写的代码也是一个好的模式。今天趁着要放假了,整理下,做个笔记。

二、代码分析

1.简单工厂模式的引入

假设我们有一个生产肉的工厂,可以生产牛肉,猪肉,都可以拿出去卖,照着这个工厂运营方式,我们可以写出这样的代码描述它的产品:

public abstract class Meat
{
    public abstract void Sell();
}

public class Pork : Meat
{
    public override void Sell()
    {
        Console.WriteLine("10元一斤.");
    }
}

public class Beef : Meat
{
    public override void Sell()
    {
        Console.WriteLine("30元一斤.");
    }
}

这个时候如果来了牛肉订单,需要生产牛肉,那么我们需要创建牛肉的实例,但是过一会儿又可能是猪肉订单,也就是说这个订单不定,所以用一个对象表示,就是Meat类型。我们创建猪肉和牛肉实例的代码大概是这样:

string meatType = "牛肉"; //不确定
Meat meat;
switch(meatType)
{
    case "猪肉":
        meat = new Pork();
        break;
    case "牛肉":
        meat = new Beef();
        break;
}

这样调用显得有些难看,而且对于调用者来说也不方便,就像客户下订单,还要自己生产一样,因此考虑封装性,把这个部分单独写个工厂类,由此才有了简单工厂模式:

public class MeatFactory
{
    public Meat CreateMeat(string meatType)
    {
        Meat meat;
        switch(meatType)
        {
            case "猪肉":
                meat = new Pork();
                break;
            case "牛肉":
                meat = new Beef();
                break;
        }
        return meat;
    }
}

void Main()
{
    MeatFactory factory = new MeatFactory();
    Meat meat = factory.CreatMeat("猪肉");
}

这样子,客户只管说生产什么就行了,也不用关心怎么生产的,确实方便了。

2.抽象工厂模式

在简单工厂模式上玩的确实还行,可是突然有一天,猪肉的生产方式变了,跟牛肉不一样了,我们就不能用原来的方式生产猪肉了,这才发现,简单的工厂模式生产方式固定死了,不能多样化。为了实现多样化,就需要对工厂进行抽象,分出多个工厂,猪肉厂专门生产猪肉,牛肉厂专门生产牛肉,由此便有了抽象工厂模式:

public abstract class MeatFactory
{
    public abstract Meat CreateMeat();
}

public class PorkFactory : MeatFactory
{
    public override Meat CreateMeat()
    {
        Meat meat = new Pork();
        //增加一些操作,比如去毛,添加剂等等
        return meat;
    }
}
public class BeefFactory : MeatFactory
{
    public override Meat CreateMeat()
    {
        Meat meat = new Beef();
        //增加一些操作,比如风干等等
        return meat;
    }
}

void Main()
{
    string meatType = "牛肉"; //不确定
    Meat meat;
    MeatFactory factory;
    switch(meatType)
    {
        case "猪肉":
            factory = new PorkFactory();
            break;
        case "牛肉":
            factory = new BeefFactory();
            break;
    }
    meat = factory.CreateMeat();
}

这样来看,抽象工厂确实解决了产品生产方式改变的问题。客户也还算满意,但是他觉得,他才不关心你哪个工厂产的,调用太麻烦了,这样我们又回到了简单工厂模式遇到的问题,或许我们可以再套个简单工厂封装下调用部分,调用的人就不用管怎么生产的了,这里就不展示代码了,参考简单工厂。

3.延伸

上面的处理方式确实让客户满意了,因为他也不用管内部怎么生产的,可是我不一样啊,我得管啊。每新增一种肉,我就得写一个switch,case,一旦增加的多了,这代码可就长了,并没有什么效率可言,跟最开始比,代码量差不多啊。细想工厂模式只是个编程思想,也并不是标准答案,需要根据情况自行改变,因此我们可以对这个创建实例部分进行改进。客户不想知道怎么生产的,我们也同样不想知道客户下的什么订单,我们可以让代码自己去找,可以使用反射来实现:

void Main()
{
    string meatType = "Pork"; //不确定
    Meat meat;
    MeatFactory factory;
    Type personType = Type.GetType(meatType); //需要加上命名空间
    factory = (MeatFactory)Activator.CreateInstance(personType);
    meat = factory.CreateMeat();
}

这样就不用写那么多case了,管他要什么,只要字符没写错,统统接收。

三、总结

工厂模式非常实用,其本质就是利用类的继承搭起来的,再附加抽象类的特性,基本所有软件都会用到吧。了解本质之后就会发现,并没有什么特殊的,只要吃透面向对象三个特性,什么模式都是一样,而且任何模式都不能生搬硬套。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值