为什么需要工厂
我们来看看,当没有工厂时引发的问题
业务情景,当前有许多卖手机的店,里面卖着各种型号的手机,当前卖了苹果,三星,oppo,三款手机
当前设计
对应代码
IPhone
package headfirst.hd.factory.phone;
public class IPhone {
public double price = 6000;
}
Samsung
package headfirst.hd.factory.phone;
public class Samsung{
public double price = 5000;
}
Oppo
package headfirst.hd.factory.phone;
public class Oppo{
public double price = 2888;
}
PhoneStore ,当前需要卖一个IPhone手机
package headfirst.hd.factory.phone;
public class PhoneStore {
public void salePhone() {
IPhone iPhone = new IPhone();
System.out.println(iPhone.price);
}
}
测试类
Client
package headfirst.hd.factory.phone;
public class Client {
public static void main(String[] args) {
PhoneStore phoneStore = new PhoneStore();
phoneStore.salePhone();
}
}
问题来了
当我们需要卖其他手机的时候,我们需要修改PhoneStore类,如下当我们需要卖Oppo手机时
package headfirst.hd.factory.phone;
public class PhoneStore {
public void salePhone() {
Oppo oppo= new Oppo();
System.out.println(oppo.price);
}
}
引入简单工厂
为了解决以上问题,我们引入简单工厂,通过接收的参数的不同来返回不同的对象实例。
简单工厂模型
重写设计模型
我们将手机抽象成接口,使用工厂类有一个共同的产品类型
设计为
重要代码为,以下修改
package headfirst.hd.factory.phone;
public interface Phone {
void salePrice();
}
package headfirst.hd.factory.phone;
public class IPhone implements Phone {
public double price = 6000;
@Override
public void salePrice() {
System.out.println(price);
}
}
package headfirst.hd.factory.phone;
public class Oppo implements Phone {
public double price = 2888;
@Override
public void salePrice() {
System.out.println(price);
}
}
package headfirst.hd.factory.phone;
public class Samsung implements Phone {
public double price = 5000;
@Override
public void salePrice() {
System.out.println(price);
}
}
package headfirst.hd.factory.phone;
public class SimpleFactory {
enum PhoneType {
IPHONE,OPPO,SAMSUNG
}
public Phone createProduct(PhoneType type) {
Phone phone = null;
if (PhoneType.IPHONE == type) {
phone = new IPhone();
} else if (PhoneType.OPPO == type) {
phone = new Oppo();
} else if (PhoneType.SAMSUNG == type) {
phone = new Samsung();
}
return phone;
}
}
package headfirst.hd.factory.phone;
import headfirst.hd.factory.phone.SimpleFactory.PhoneType;
public class PhoneStore {
SimpleFactory simpleFactory;
public PhoneStore(SimpleFactory simpleFactory) {
this.simpleFactory = simpleFactory;
}
public void salePhone(PhoneType type) {
if (simpleFactory == null) {
throw new NullPointerException("simpleFactory未初始化!!!");
}
Phone phone = simpleFactory.createProduct(type);
phone.salePrice();
}
}
package headfirst.hd.factory.phone;
import headfirst.hd.factory.phone.SimpleFactory.PhoneType;
public class Client {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
PhoneStore phoneStore = new PhoneStore(factory);
phoneStore.salePhone(PhoneType.IPHONE);
}
}
可以看到,简单工厂将创建实例统一管理起来,这是他的优点
缺点是当我们需要新增一种类型,必须打开createProduct方法,如下,我们添加XiaoMi手机类型
新增手机类型,小米XiaoMi
package headfirst.hd.factory.phone;
public class XiaoMi implements Phone {
public double price = 1999;
@Override
public void salePrice() {
System.out.println(price);
}
}
修改SimpleFactory
package headfirst.hd.factory.phone;
public class SimpleFactory {
enum PhoneType {
IPHONE,OPPO,SAMSUNG,XIAOMI
}
public Phone createProduct(PhoneType type) {
Phone phone = null;
if (PhoneType.IPHONE == type) {
phone = new IPhone();
} else if (PhoneType.OPPO == type) {
phone = new Oppo();
} else if (PhoneType.SAMSUNG == type) {
phone = new Samsung();
} else if (PhoneType.XIAOMI == type) {
phone = new XiaoMi();
}
return phone;
}
}
PS:简单工厂不是设计模式
引入工厂方法模式
为了解决以上问题,我们引入工厂方法模式,通过逻辑拆分,将创建实例封装在不同的工厂中,例如,IPhone有很多款手机,XiaoMi也有很多款手机,当IPhone发布新手机的时候,我们需要改变IPhone对应的工厂
工厂方法模式模型
重写设计新模型
这里只贴与factory相关的代码,重点说明一下工厂方法模式
PhoneFactory
package headfirst.hd.factory.phone;
public abstract class PhoneFactory {
//父类定义抽象接口,不管子类具体是哪一种类型
public void salePhone(String type) {
Phone phone = createProduct(type);
phone.salePrice();
}
//子类只实现这个方法,其他的什么都不做
protected abstract Phone createProduct(String type);
}
XiaoMiPhoneFactory
package headfirst.hd.factory.phone;
public class XiaoMiPhoneFactory extends PhoneFactory {
@Override
protected Phone createProduct(String type) {
Phone phone = null;
if ("XiaoMi2".equals(type)) {
phone = new XiaoMi2();
} else if ("XiaoMi3".equals(type)) {
phone = new XiaoMi3();
}
return phone;
}
}
IPhonePhoneFactory
package headfirst.hd.factory.phone;
public class IPhonePhoneFactory extends PhoneFactory {
@Override
protected Phone createProduct(String type) {
Phone phone = null;
if ("IPhone4".equals(type)) {
phone = new IPhone4();
} else if ("IPhone5".equals(type)) {
phone = new IPhone5();
}
return phone;
}
}
测试Client
package headfirst.hd.factory.phone;
public class Client {
public static void main(String[] args) {
//卖小米4
PhoneFactory factory = new XiaoMiPhoneFactory();
factory.salePhone("XiaoMi2");
}
}
重要说明
- 工厂方法模式,其中方法指的子类里只实现父类的抽象方法,而父亲提供产品的行为,工厂方法模式将两者解耦,使类责任单一化
- 与简单工厂的相似性,如果单单看其中某一个工厂,和所对应的产品,工厂方法模式和简单工厂很类似,如下图所示
- 站在PhoneFactory角度看,我们将原来简单工厂的逻辑,按照业务拆分成多个方法
- 当我们新增具体的产品时候
- 当前新增手机IPhone6,简单工厂会修改SimpleFactory中的代码,工厂方法模式修改IPhonePhoneFactory中的代码,不会影响XiaoMiPhoneFactory中的代码,将影响降低
- 当前新增手机XiaoMi4,简单工厂会修改SimpleFactory中的代码,工厂方法模式修改XiaoMiPhoneFactory中的代码,不会影响IPhonePhoneFactory中的代码,将影响降低
- 当我们新增新类型手机,例如VIVO,单工厂会修改SimpleFactory中的代码,工厂方法模式新增VivoPhoneFactory类,不会影响到已有类,最理想的状态
简单工厂对需求已知时候,毕竟适应,产品需求经常变话时,工厂方法模式更加适应
抽象工厂模式
以上问题都是单一产品。抽象工厂是应对产品族概念的。比如说,每一款手机由屏幕,处理器,内存等组成。其中屏幕,电量,内存都对应的一类产品。那么每一个工厂创建手机的组成时候,需要创建对应组成部分。
这里的产品对应的是屏幕(很多种),电量(很多种),内存(很多种)
抽象工厂模式模型
iPhone X的手机的一些配置
当前设计
对应代码
产品家族Battery
package headfirst.hd.factory.abs;
public interface Battery {
//这里简化,不做任何操作
}
package headfirst.hd.factory.abs;
public class Battery1 implements Battery {
}
package headfirst.hd.factory.abs;
public class Battery2 implements Battery {
}
产品家族Memory
package headfirst.hd.factory.abs;
public interface Memory {
//这里简化,不做任何操作
}
package headfirst.hd.factory.abs;
public class Memory1 implements Memory {
}
package headfirst.hd.factory.abs;
public class Memory2 implements Memory {
}
产品家族Screen
package headfirst.hd.factory.abs;
public interface Screen {
//这里简化,不做任何操作
}
package headfirst.hd.factory.abs;
public class Screen1 implements Screen {
}
package headfirst.hd.factory.abs;
public class Screen2 implements Screen {
}
抽象工厂
package headfirst.hd.factory.abs;
public interface IPhoneXFactory {
Screen createScreen();
Battery createBattery();
Memory createMemory();
}
package headfirst.hd.factory.abs;
//普通版本,8333
public class NormalFactory implements IPhoneXFactory {
@Override
public Screen createScreen() {
return new Screen1();
}
@Override
public Battery createBattery() {
return new Battery1();
}
@Override
public Memory createMemory() {
return new Memory1();
}
}
package headfirst.hd.factory.abs;
//plus版本,10000
public class PlusFactory implements IPhoneXFactory {
@Override
public Screen createScreen() {
return new Screen2();
}
@Override
public Battery createBattery() {
return new Battery2();
}
@Override
public Memory createMemory() {
return new Memory2();
}
}
定义手机
package headfirst.hd.factory.abs;
public class IPhone {
IPhoneXFactory factory;
public IPhone(IPhoneXFactory factory) {
this.factory = factory;
}
//手机的一些操作
public void doOperate() {
//屏幕
//内存
//电池
}
}
测试
package headfirst.hd.factory.abs;
public class Client {
public static void main(String[] args) {
//整一个plus版本
IPhoneXFactory factory = new PlusFactory();
IPhone iPhone = new IPhone(factory);
iPhone.doOperate();
}
}
缺点,如果现在新增处理器产品,则必须修改抽象工厂接口,如下
产品
package headfirst.hd.factory.abs;
public interface Cpu {
//这里简化,不做任何操作
}
抽象接口
package headfirst.hd.factory.abs;
public interface IPhoneXFactory {
Screen createScreen();
Battery createBattery();
Memory createMemory();
Cpu createCpu();
}
影响已有代码
总结
整理 | 优点 | 缺点 |
---|---|---|
简单工厂 | 用来生产同一等级结构中的任意产品,且设计简单 | 对于增加新的产品,必须修改原有代码 |
工厂方法模式 | 用来生产同一等级结构中任意产品,是对简单工厂的增强 | 将影响降到最低 |
抽象工厂模式 | 用来生产不同产品族的产品 | 如何新增产品,必须修改抽象工厂接口 |
可根据实际需求,选择对应的方法