设计模式之工厂模式

概述

工厂,就是生产产品的地方。在Java设计模式中使用工厂的概念,那就是生成对象的地方了。本来直接就能创建的对象为何要增加一个工厂类呢?

这就需要了解工厂方法要解决的是什么问题了,如果只有一个类,我们直接new一个对象完事,这是最简单的;但是如果有多个类呢,而且这些类还需要针对不同的情况来创建不同的对象,这时候就需要工厂了,我们可以在工厂中根据条件来创建具体的对象。这样一来就将调用方和具体的目标类进行了解耦,调用方根本就不知道需要创建那个对象,它只是提出了条件,然后工厂就可以根据给定的条件来决定创建哪一个对象。

举个栗子:

假如有个厂商代生产手机,它当前可以生产华为手机,随着业务的扩展,这个代工厂还要生产小米和OPPO手机,这样我们就需要一个类去生产这些手机,这就用到了简单工厂模式。接下来我们先看一下简单工厂模式的实现。

简单工厂模式

我们创建一个计算机的抽象产品类,其中有一个抽象方法用于启动手机,如下所示。

public abstract class Phone {
    //产品的抽象方法,由具体的产品类实现
    public abstract void product();
}

接着我们创建各个品牌的手机,都继承了自己的父类Phone,并实现了父类的product方法。

public class HUAWEIPhone extends Phone {

    @Override
    public void product() {
        System.out.println("生产华为手机");
    }
}
public class OPPOPhone extends Phone {
    @Override
    public void product() {
        System.out.println("生产OPPO手机");
    }
}
public class XiaoMiPhone extends Phone {
    @Override
    public void product() {
        System.out.println("生产小米手机");
    }
}

工厂类

public class PhoneFactory {
    public static Phone productPhone(String type) {
        Phone mPhone = null;
        switch (type) {
            case "huwei":
                mPhone = new HUAWEIPhone();
                break;
            case "oppo":
                mPhone = new OPPOPhone();
                break;
            case "xiaomi":
                mPhone = new XiaoMiPhone();
                break;
        }
        return mPhone;
    }
}

客户端调用工厂类

public class ProductPhone {
    public static void main(String[] args) {
        PhoneFactory.productPhone("huawei").product();
    }
}

使用简单工厂模式的场景和优缺点

  • 使用场景
  1. 工厂类负责创建对象比较少
  2. 客户只需要知道传入工厂类的参数,而无需关系创建对象的逻辑。
  • 优点:使用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性。
  • 缺点:可实例化的类型在编译期间已经被确定。如果增加新类型,则需要修改工厂,这违背了开放封闭原则。简单工厂需要知道所有要生成的类型,其当子类过多或者子类层次过多时不适合使用。

工厂方法模式

定义:定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到子类。

创建抽象工厂

抽象工厂创建一个方法来生产各种手机

public abstract class PhoneFactory {
    public abstract <T extends Phone> T productPhone(Class<T> clz);
}

具体工厂

海外代工厂是一个具体的工厂,其继承抽象工厂,通过反射来生产不同厂家的手机

public class HWPhoneFactory extends PhoneFactory {
    @Override
    public <T extends Phone> T productPhone(Class<T> clz) {
        Phone mPhone = null;
        String className = clz.getName();
        try {
            //通过反射来生产不同厂家的手机
            mPhone = (Phone) Class.forName(className).newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

客户端调用

public class Client {
    public static void main(String[] args) {
        PhoneFactory mPhoneFactory = new HWPhoneFactory();
        HUAWEIPhone mHUAWEIPhone = mPhoneFactory.productPhone(HUAWEIPhone.class);
        mHUAWEIPhone.product();
        OPPOPhone mOPPOPhone = mPhoneFactory.productPhone(OPPOPhone.class);
        mOPPOPhone.product();
        XiaoMiPhone mXiaoMiPhone = mPhoneFactory.productPhone(XiaoMiPhone.class);
        mXiaoMiPhone.product();
    }
}

总结:

对于简单工厂模式,我们都知道其在工厂类中包含了必要的逻辑判断,根据不同的条件来动态实例化相关的类。对客户端来说,这去除了具体产品的依赖;但与此同时也会带来一个问题:如果我们要增加产品,比如我们要生产苹果手机,就需要在工厂模式类中添加一个case分支条件,这违背了开放封闭原则,对修改也开放了。而工厂方法模式就没有违背这个开放封闭原则。如果我们需要生产苹果手机,则无需修改工厂类,直接创建产品即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万子开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值