设计模式整理(5) 工厂模式

学习《Android 源码设计模式解析与实践》系列笔记

介绍

工厂模式属于创建型设计模式之一,是一种结构简单的设计模式,也是应用广泛的设计模式。
工厂模式是用来实例化对象的模式,是用工厂方法代替 new 操作的一种模式。这种替代可以给系统带来更好的可扩展性。

定义

定义一个用于创建对象的接口,让子类决定实例化哪个类。

使用场景

在任何需要生产复杂对象的地方,都可以使用工厂模式。复杂对象适合使用工程模式,用 new 就可以完成创建的对象无需使用工厂模式。

分类

工厂模式主要分为三种:

  • 简单工厂模式(静态工厂模式)
  • 工厂方法模式
  • 抽象工厂模式

简单工厂模式

简单工厂模式结构

简单工厂模式 UML 图

  • AbstractProduct : 抽象产品类
  • ConcreteProductA(B/C) : 具体产品类
  • Factory : 工厂类,负责实例化各种产品

简单工厂模式实现

假设一家奥迪的汽车工厂,需要生产 Q3、Q5、Q7 三个车型的汽车。因为这三个车型内部结构相差不是特别大,所以为了节约成本,只要需要一条生产线就可以了。

/**
 * 抽象产品类,汽车
 */
public abstract class Car {
    public abstract void drive();
}
/**
 * 具体产品类
 */
public class AudiQ3 extends Car {
    @Override
    public void drive() {
        System.out.println("AudiQ3 drive");
    }
}
/**
 * 具体产品类
 */
public class AudiQ5 extends Car {
    @Override
    public void drive() {
        System.out.println("AudiQ5 drive");
    }
}
/**
 * 具体产品类
 */
public class AudiQ7 extends Car {
    @Override
    public void drive() {
        System.out.println("AudiQ7 drive");
    }
}
**
 * 工厂类
 */
public class AudiFactory {

    public static Car createCar(String carType) {
        if (carType == null) {
            return null;
        } else if ("Q3".equals(carType)) {
            return new AudiQ3();
        } else if ("Q5".equals(carType)) {
            return new AudiQ5();
        } else if ("Q7".equals(carType)) {
            return new AudiQ7();
        } else {
            return null;
        }
    }

}
public class Client {

    public static void main(String args[]) {
        Car audiQ3 = AudiFactory.createCar("Q3");
        audiQ3.drive();
        Car audiQ5 = AudiFactory.createCar("Q5");
        audiQ5.drive();
        Car audiQ7 = AudiFactory.createCar("Q7");
        audiQ7.drive();
    }

}

打印结果:

AudiQ3 drive
AudiQ5 drive
AudiQ7 drive

工厂方法模式

工厂方法模式结构

工厂方法模式 UML 图

  • AbstractProduct : 抽象的产品类
  • ConcreteProductA(B/C) : 具体的产品类
  • AbstractFactory : 抽象的工厂类
  • ConcreteFactoryA(B/C) : 具体的工厂类

工厂方法模式实现

随着工厂的不断发展,业务做得越来越大了,所有车型都在一条生产线上生产,问题也频繁出现了。而且随着新的车型出来,发现这条生产线不适应了,又得修改。于是,为了更好的解决这些问题,以及考虑到后续发展可能会有更多的车型投入生产,每个车型都单独使用一条生产线生产。

/**
 * 抽象产品类,汽车
 */
public abstract class Car {
    public abstract void drive();
}
/**
 * 具体产品类
 */
public class AudiQ3 extends Car {
    @Override
    public void drive() {
        System.out.println("AudiQ3 drive");
    }
}
/**
 * 具体产品类
 */
public class AudiQ5 extends Car {
    @Override
    public void drive() {
        System.out.println("AudiQ5 drive");
    }
}
/**
 * 具体产品类
 */
public class AudiQ7 extends Car {
    @Override
    public void drive() {
        System.out.println("AudiQ7 drive");
    }
}
/**
 * 抽象工厂类
 */
public abstract class Factory {

    public abstract Car createCar();

}
/**
 * 具体的工厂类
 */
public class AudiQ3Factory extends Factory {
    @Override
    public Car createCar() {
        return new AudiQ3();
    }
}
/**
 * 具体的工厂类
 */
public class AudiQ5Factory extends Factory {
    @Override
    public Car createCar() {
        return new AudiQ5();
    }
}
/**
 * 具体的工厂类
 */
public class AudiQ7Factory extends Factory {
    @Override
    public Car createCar() {
        return new AudiQ7();
    }
}
public class Client {

    public static void main(String args[]) {
        Car audiQ3 = new AudiQ3Factory().createCar();
        audiQ3.drive();
        Car audiQ5 = new AudiQ5Factory().createCar();
        audiQ5.drive();
        Car audiQ7 = new AudiQ7Factory().createCar();
        audiQ7.drive();
    }

}

工厂方法模式相较于简单工厂模式,扩展性更好了,耦合性更低了。
简单工厂模式把所有的实例化的工作都放在一个方法中,通过传入的类型来判断具体返回的对象。假如传入的类型有误,就会导致得到错误的对象。或者当有新的产品出来了,又需要修改这个构造产品的方法。
工厂方法模式把构造每个类型产品的方法都独立了出来,每次有新的产品时,只需要添加新的工厂或者方法,这样扩展性会更好。

但是,每次添加新的产品,都需要添加新的工厂,这样还是太麻烦了,于是,这里还有改进的办法。
这里主要是针对 Factory 部分做了优化,通过反射的方式,返回传入类的实例:

/**
 * 抽象的工厂类
 */
public abstract class AbstractFatory {

    public abstract <T extends Car> T createCar(Class<T> clz);

}
/**
 * Created by linpu on 2019/2/12 .
 */
public class AudiCarFactory extends AbstractFatory {
    @Override
    public <T extends Car> T createCar(Class<T> clz) {
        Car car = null;
        try {
            car = (Car) Class.forName(clz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) car;
    }
}
public class Client {

    public static void main(String args[]) {
        AudiCarFactory factory = new AudiCarFactory();
        Car audiQ3 = factory.createCar(AudiQ3.class);
        audiQ3.drive();
        Car audiQ5 = factory.createCar(AudiQ5.class);
        audiQ5.drive();
        Car audiQ7 = factory.createCar(AudiQ7.class);
        audiQ7.drive();
    }

}

抽象工厂模式

前面介绍的工厂模式都是,每个工厂都会生产某一种具体的产品。而抽象工厂生产的产品时不确定的。

抽象工厂模式定义

抽象工厂模式是为创建一组相关或者是相互依赖的对象提供的一个接口,而不需要指定他们的具体类。

抽象工厂模式结构

抽象工厂模式 UML 图

  • AbstractFactory : 抽象工厂,声明了一组用于创建一种产品的方法,每个方法对应一种产品。
  • ConcreteFactory : 具体的工厂类
  • AbstractPruduct : 抽象的产品类
  • ConcreteProduct : 具体的产品类

抽象工厂模式实现

在上诉的汽车厂中,虽然 Q3、Q5、Q7都是一个车系,都是三者之间的零部件差别是很大的。比如说 Q3 的发动机是国产的,而 Q7 的是进口的;Q3 的是普通轮胎,而 Q7 的是越野轮胎;Q3 的是普通制动系统,Q7 的是制动性能很好的新制动系统。Q3、Q5、Q7 是一系列车,而发动机、轮胎、制动系统是一系列零部件,两者是不同的产品类型。所以,在生产不同的车型时,需要生产不同的零部件。

轮胎相关类:

/**
 * 抽象轮胎类
 */
public abstract class Tire {

    public abstract void tire();

}
/**
 * 普通轮胎类
 */
public class NormalTire extends Tire {
    @Override
    public void tire() {
        System.out.println("普通轮胎");
    }
}
/**
 * 越野车轮胎类
 */
public class SUVTire extends Tire {
    @Override
    public void tire() {
        System.out.println("越野轮胎");
    }
}

发动机相关类:

/**
 * 抽象发动机类
 */
public abstract class Engine {

    public abstract void engine();

}
/**
 * 国产发动机类
 */
public class DomesticEngine extends Engine {
    @Override
    public void engine() {
        System.out.println("国产发动机");
    }
}
/**
 * 进口发动机类
 */
public class ImportEngine extends Engine {
    @Override
    public void engine() {
        System.out.println("进口发动机");
    }
}

制动系统相关类:

/**
 * 抽象制动系统类
 */
public abstract class Brake {
    public abstract void brake();
}
/**
 * 普通制动系统类
 */
public class NormalBrake extends Brake {
    @Override
    public void brake() {
        System.out.println("普通制动系统");
    }
}
/**
 * 高级制动系统类
 */
public class SeniorBrake extends Brake {
    @Override
    public void brake() {
        System.out.println("高级制动系统");
    }
}

工厂相关类:

/**
 * 抽象工厂类
 */
public abstract class CarFactory {

    /**
     * 生产轮胎
     * @return
     */
    public abstract Tire createTire();

    /**
     * 生产发动机
     * @return
     */
    public abstract Engine createEngine();

    /**
     * 生产制动系统
     * @return
     */
    public abstract Brake createBrake();
}
/**
 * Q3 工厂类
 */
public class Q3Factory extends CarFactory {
    @Override
    public Tire createTire() {
        return new NormalTire();
    }

    @Override
    public Engine createEngine() {
        return new DomesticEngine();
    }

    @Override
    public Brake createBrake() {
        return new NormalBrake();
    }
}
/**
 * Q7 工厂类
 */
public class Q7Factory extends CarFactory {
    @Override
    public Tire createTire() {
        return new SUVTire();
    }

    @Override
    public Engine createEngine() {
        return new ImportEngine();
    }

    @Override
    public Brake createBrake() {
        return new SeniorBrake();
    }
}

客户类:

public class Client {

    public static void main(String args[]) {
        CarFactory q3Factory = new Q3Factory();
        q3Factory.createTire().tire();
        q3Factory.createEngine().engine();
        q3Factory.createBrake().brake();

        System.out.println("------------------");

        CarFactory q7Factory = new Q7Factory();
        q7Factory.createTire().tire();
        q7Factory.createEngine().engine();
        q7Factory.createBrake().brake();
    }

}

输出结果:

普通轮胎
国产发动机
普通制动系统
------------------
越野轮胎
进口发动机
高级制动系统

无论是 Q3Factory 还是 Q7Factory,它们都不再是生产单一的产品,而是一系列相关的产品。

总结

无论是哪种工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。工厂模式在给我们带来诸多好处的同时,因为引入抽象层等,会导致类结构的复杂化。


相关文章:

设计模式整理(1) 代理模式
设计模式整理(2) 单例模式
设计模式整理(3) Builder 模式
设计模式整理(4) 原型模式
设计模式整理(5) 工厂模式
设计模式整理(6) 策略模式
设计模式整理(7) 状态模式
设计模式整理(8) 责任链模式
设计模式整理(9) 观察者模式
设计模式整理(10) 适配器模式
设计模式整理(11) 装饰模式
设计模式整理(12) 中介者模式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值