设计模式-工厂模式-3种-以手机制造工厂为例

超级链接: Java常用设计模式的实例学习系列-绪论

参考:《HeadFirst设计模式》


1.工厂模式存在的意义

工厂存在的意义是:高效的制造某一类产品。

工厂模式存在的意义是:高效的创建某一类对象。

工厂模式有很多种,本文只介绍以下三种:

  • 简单工厂模式,又称静态工厂模式
  • 工厂方法模式,全称多个工厂方法模式
  • 抽象工厂模式

本文以`手机制造工厂生产手机为场景来学习工厂模式。

  • 手机有两种:苹果手机和安卓手机。
  • 手机制造工厂分别可以制造上述两种手机。

2.关于手机

关于手机的编码不过多的叙述,就是很简单的一个父抽象类加两个子实现类的关系。

父抽象手机类:Phone

/**
 * <p>手机</P>
 *
 * @author hanchao
 */
@Getter
@Setter
@AllArgsConstructor
public abstract class Phone {
    private String name;

    /**
     * 打个电话测试一下
     */
    public abstract void callTest();
}

子实现类:苹果手机:ApplePhone

/**
 * <p>苹果手机</P>
 *
 * @author hanchao
 */
@Slf4j
public class ApplePhone extends Phone {

    public ApplePhone() {
        super("苹果手机");
    }

    @Override
    public void callTest() {
        log.info("使用[" + super.getName() + "]给13322224444打电话.");
    }
}

子实现类:安卓手机:AndroidPhone

/**
 * <p>安卓手机</P>
 *
 * @author hanchao
 */
@Slf4j
public class AndroidPhone extends Phone {

    public AndroidPhone() {
        super("安卓手机");
    }

    @Override
    public void callTest() {
        log.info("使用[" + super.getName() + "]给15533335555打电话.");
    }
}

3.简单/静态工厂模式

简单工厂模式:一般情况下,创建对象的方法需要传入代表类型的参数type,然后再通过if-else或者switch语句根据type创建对应的对象。

直接上代码:PhoneFactory

/**
 * <p>简单工厂:手机工厂</P>
 *
 * @author hanchao
 */
public class PhoneFactory {
    public static final int TYPE_APPLE = 1;
    public static final int TYPE_ANDROID = 2;

    /**
     * 简单工厂:一般情况下,创建对象的方法需要传入代表类型的参数type,然后再通过if-else或者switch语句根据type创建对应的对象。
     */
    public static Phone producePhone(int type) {
        Phone phone;
        switch (type) {
            case TYPE_APPLE:
                //制造一个苹果手机
                phone = new ApplePhone();
                break;
            case TYPE_ANDROID:
                //制造一个安卓手机
                phone = new AndroidPhone();
                break;
            default:
                throw new IllegalArgumentException("此型号手机暂不制造!");
        }
        return phone;
    }
}
  • 简单工厂的机制很简单:根据传入的类型,创建对应的对象。

  • 这里将可用的类型编写成了静态变量,这用能在一定程度上减少出错的可能。

然后,写一个简单的测试类:SimpleFactoryDemo

/**
 * <p>1.简单工厂模式</P>
 *
 * @author hanchao
 */
public class SimpleFactoryDemo {

    public static void main(String[] args) {
        //某客户下了一笔大单子,要求制造2台苹果手机和1台安卓手机
        //于是手机工厂开始了制造

        //先来一台苹果手机
        Phone phone = PhoneFactory.producePhone(PhoneFactory.TYPE_APPLE);
        //测试一下
        phone.callTest();

        //再来一台苹果手机
        phone = PhoneFactory.producePhone(PhoneFactory.TYPE_APPLE);
        //测试一下
        phone.callTest();

        //再来一台安卓手机
        phone = PhoneFactory.producePhone(PhoneFactory.TYPE_ANDROID);
        //测试一下
        phone.callTest();
    }
}

运行结果:

2019-06-30 15:03:10,353  INFO [main-1] pers.hanchao.designpattern.factory.simple.telephone.ApplePhone:19 - 使用[苹果手机]给13322224444打电话. 
2019-06-30 15:03:10,357  INFO [main-1] pers.hanchao.designpattern.factory.simple.telephone.ApplePhone:19 - 使用[苹果手机]给13322224444打电话. 
2019-06-30 15:03:10,358  INFO [main-1] pers.hanchao.designpattern.factory.simple.telephone.AndroidPhone:19 - 使用[安卓手机]给15533335555打电话. 

3.1.简单/静态工厂模式的总结

**简单工厂:**一般情况下,创建对象的方法需要传入代表类型的参数type,然后再通过if-else或者switch语句根据type创建对应的对象。

通常提供的创建对象的方法是静态的,所以简单工厂模式也称之为静态工厂模式

3.2.简单/静态工厂模式的优点

  • 实现简单:代码逻辑很简单。
  • 可复用高:所有对象的创建都通过同名的方法创建。

3.3.简单/静态工厂模式的缺点

  • 容错率低,如果传入的类型参数type因为粗心写错,则创建的产品会与预期不符。
  • 耦合度高,每增减一种产品,都需要对创建对象的唯一方法进行修改。
  • 扩展性差,每增减一种产品,都需要修改工厂类,违背了设计模式的开放-封闭原则(OCP,对扩展开放,对修改关闭)。

造成以上缺点的关键在于:所有对象的创建都通过唯一的工厂方法。

为了解决以上问题,尝试为每种对象提供相应的工厂方法。如此进化成了:多个工厂方法模式。

4.(多个)工厂方法模式

(多个)工厂方法模式的关键点在于:为每种对象提供相应的工厂方法,所以很容易得到如下的工厂类:

PhoneFactory

/**
 * <p>多个工厂方法模式:手机工厂</P>
 *
 * @author hanchao
 */
public class PhoneFactory {

    /**
     * 制造一个苹果手机
     */
    public static Phone produceApplePhone() {
        return new ApplePhone();
    }

    /**
     * 制造一个安卓手机
     */
    public static Phone produceAndroidPhone() {
        return new AndroidPhone();
    }
}

然后,写一个简单的测试类:MultiFactoryMethodsDemo

/**
 * <p>2.多个工厂方法模式</P>
 *
 * @author hanchao
 */
public class MultiFactoryMethodsDemo {

    public static void main(String[] args) {
        //某客户下了一笔大单子,要求制造2台苹果手机和1台安卓手机
        //于是手机工厂开始了制造

        //先来一台苹果手机
        Phone phone = PhoneFactory.produceApplePhone();
        //测试一下
        phone.callTest();

        //再来一台苹果手机
        phone = PhoneFactory.produceApplePhone();
        //测试一下
        phone.callTest();

        //再来一台安卓手机
        phone = PhoneFactory.produceAndroidPhone();
        //测试一下
        phone.callTest();
    }
}

运行结果:略

4.1.(多个)工厂方法模式的总结

多个工厂方法模式: 每种对象分别编写专用的创建方法,根据调用的创建方法的不同,产生不同的对象。

多个工厂方法模式又简称为工厂方法模式

4.2.(多个)工厂方法模式的优点

  • 实现简单:代码逻辑很简单。
  • 容错率高,因为每种对象都有专用的创建方法,无需传入类型等参数,只要调用正确的创建方法就不会出错。
  • 耦合度低,每增减一种产品,只需要增减一个创建方法,不会影响其他对象的创建方法。

4.3.(多个)工厂方法模式的缺点

  • 扩展性差,每增减一种产品,都需要修改工厂类,违背了设计模式的开放-封闭原则(OCP,对扩展开放,对修改关闭)。
  • 可复用低,所有对象的创建方法都不同名。

造成以上缺点的关键在于:所有对象的创建方法都存在于唯一个工厂。

为了解决以上问题,尝试为每种对象提供单独的工厂及工厂方法。如此进化成了:抽象工厂模式。

5.抽象工厂模式

抽象工厂模式的关键点在于:``为每种对象提供单独的工厂及工厂方法`。

所以需要把工厂类抽象出来,形成抽象工厂,然后针对每种对象分别实现专用的工厂及工厂方法,这就是命名抽象工厂的由来。

抽象工厂:AbstractPhoneFactory

/**
 * <p>抽象手机工厂</P>
 *
 * @author hanhao
 */
public abstract class AbstractPhoneFactory {
    /**
     * 制造手机
     *
     * @return 手机
     */
    public abstract Phone producePhone();
}

苹果手机专用的工厂及创建方法:ApplePhoneFactory

/**
 * <p>具体工厂:苹果手机工厂</P>
 *
 * @author hanchao
 */
public class ApplePhoneFactory extends AbstractPhoneFactory {

    @Override
    public Phone producePhone() {
        return new ApplePhone();
    }
}

安卓手机专用的工厂及创建方法:AndroidPhoneFactory

/**
 * <p>具体工厂:安卓手机工厂</P>
 *
 * @author hanchao
 */
public class AndroidPhoneFactory extends AbstractPhoneFactory {

    @Override
    public Phone producePhone() {
        return new AndroidPhone();
    }
}

然后,写一个简单的测试类:AbstractFactoryDemo

/**
 * <p>3.抽象工厂模式</P>
 *
 * @author hanchao
 */
public class AbstractFactoryDemo {

    public static void main(String[] args) {
        //某客户下了一笔大单子,要求制造2台苹果手机和1台安卓手机
        //于是手机工厂开始了制造

        //先来一台苹果手机
        Phone phone = new ApplePhoneFactory().producePhone();
        //测试一下
        phone.callTest();

        //再来一台苹果手机
        phone = new ApplePhoneFactory().producePhone();
        //测试一下
        phone.callTest();

        //再来一台安卓手机
        phone = new AndroidPhoneFactory().producePhone();
        //测试一下
        phone.callTest();
    }
}

运行结果:略

5.1.抽象工厂模式的总结

抽象工厂模式: 定义一个抽象工厂和抽象方法,每种对象都有专用的子工厂及对象创建方法。

5.2.抽象工厂模式的优点

  • 容错率高,因为每种对象都有专用的工厂及创建方法,只要调用正确的工厂的创建方法就不会出错。
  • 耦合度低,每增减一种产品,只需增减一个工厂及创建方法,不会影响其他对象的创建方法。
  • 扩展性好,每增减一种产品,只需增减此对象的工厂及创建方法,不修改其他工厂,遵循了开放-封闭原则(OCP,对扩展开放,对修改关闭)。
  • 可复用高,所有对象的创建都通过同名的方法创建。

5.3.抽象工厂模式的缺点

  • 实现复杂:代码逻辑相对复杂。可能100种对象,需要定义100个工厂类。

6.总结

最后以UML类图来总结本文的三种工厂模式。

在这里插入图片描述

从设计模式原则考虑,上述三种工厂模式的推荐优先级:抽象工厂模式 >>>(多个)工厂方法模式>>>简单/静态工厂模式

不过凡事不绝对,如果你说你能百分百的保证业务场景不会发生变动,那你是用哪种模式都是无所谓的。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页