工厂模式是属于创建型设计模式,主要用来针对不同类型创建不同的对象,达到解偶类对象。
本文试图用例子解释清楚三种工厂模式,例子来源于CSDN,有链接的都会标注,方便日后回顾总结。跟着敲一遍再理解会容易些
工厂顾名思义就是创建产品的
产品
- 具体产品——简单工厂模式
- 具体工厂——工厂方法模式
工厂的抽象程度
- 工厂方法模式
- 抽象工厂模式
通过工厂模式,将创建产品实例的权利移交工厂,我们
不再通过new来创建我们所需的对象
,而是通过工厂来获取我们需要的产品
。降低了产品使用者与使用者之间的耦合关系
简单工厂模式
类图
简单工厂的实现的两种实现方式
实现一
Phone类:手机标准规范类(AbstractProduct)
public interface Phone {
void make();
}
MiPhone类:制造小米手机(Product1)
public class MiPhone implements Phone {
public MiPhone() {
this.make();
}
@Override
public void make() {
// TODO Auto-generated method stub
System.out.println("make xiaomi phone!");
}
}
IPhone类:制造苹果手机(Product2)
public class IPhone implements Phone {
public IPhone() {
this.make();
}
@Override
public void make() {
// TODO Auto-generated method stub
System.out.println("make iphone!");
}
}
PhoneFactory类:手机代工厂(Factory)
public class PhoneFactory {
public Phone makePhone(String phoneType) {
if(phoneType.equalsIgnoreCase("MiPhone")){
return new MiPhone();
}
else if(phoneType.equalsIgnoreCase("iPhone")) {
return new IPhone();
}
return null;
}
}
演示:
public class Demo {
public static void main(String[] arg) {
PhoneFactory factory = new PhoneFactory();
Phone miPhone = factory.makePhone("MiPhone"); // make xiaomi phone!
IPhone iPhone = (IPhone)factory.makePhone("iPhone"); // make iphone!
}
}
缺点:新增一个类,需要修改PhoneFactory类,添加if…else
实现二,反射方式
public class SimpleFactoryReflection{
private static final Map<EnumProductType, Class> activityIdMap = new HashMap<>();
//添加产品到缓存(类似先存到工厂)
public static void addProductKey(EnumProductType EnumProduct, Class product){
activityIdMap.put(EnumProduct, product);
}
// 使用反射制造产品(工厂 生产 产品)
public static ActivityOne product(EnumProductType type) throws IllegalAccessException, InstantiationException {
Class productClass = activityIdMap.get(type); // 获取Class的实例的方式
return (ActivityOne)productClass.newInstance();
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
/**
* 得到对象的过程
* 添加新的类时不需大动干戈,只要修改一点点就好。
*/
addProductKey(EnumProductType.activityOne,ActivityOne.class);
ActivityOne product = product(EnumProductType.activityOne);
System.out.println(product.toString());
}
public static class Product{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//对象1
public static class ActivityOne extends Product{
private String stock;
@Override
public String toString() {
return "activityOne{" +
"stock='" + stock + '\'' +
'}';
}
}
//对象2
public static class ActivityTwo extends Product{
private String stock;
}
/**
* 添加新对象
* ..........
*/
public enum EnumProductType{
activityOne,activityTwo;
}
}
工厂方法模式
类图
也就是定义一个抽象工厂,其定义了产品的生产接口,但不负责具体的产品,将生产任务交给不同的派生类工厂。这样不用通过指定类型来创建对象了。
还是使用上面的手机案例来解释
和产品相关的Phone类、MiPhone类和IPhone类的定义不变(这些就是类)
AbstractFactory类
:生产不同产品的工厂的抽象类
public interface AbstractFactory {
Phone makePhone();
}
XiaoMiFactory类
:生产小米手机的工厂(ConcreteFactory1),抽象类的具体实现
public class XiaoMiFactory implements AbstractFactory{
@Override
public Phone makePhone() {
return new MiPhone();
}
}
AppleFactory类
:生产苹果手机的工厂(ConcreteFactory2),抽象类的具体实现
public class AppleFactory implements AbstractFactory {
@Override
public Phone makePhone() {
return new IPhone();
}
}
演示:
public class Demo {
public static void main(String[] arg) {
AbstractFactory miFactory = new XiaoMiFactory();
AbstractFactory appleFactory = new AppleFactory();
miFactory.makePhone(); // make xiaomi phone!
appleFactory.makePhone(); // make iphone!
}
}
简单工厂模式和工厂方法模式总结
简单工厂和工厂方法模式的不同在于前者生成产生产品的行为
封装在一个方法中
,根据参数的类型进行实例化
,同时不存在抽象接口。而后者则增加了抽象工厂,通过实现不同的工厂方法
来创建不同的产品,一个方法通常对应一个产品,这种方式相较于前者扩展性更高,在需求增加时完全符合开闭原则和依赖倒置原则
抽象工厂模式
上面两种模式不管工厂怎么拆分抽象,都只是针对一类产品Phone(AbstractProduct),如果要生成另一种产品PC,应该怎么表示呢?
最简单的方式是把2中介绍的工厂方法模式完全复制一份,不过这次生产的是PC。但同时也就意味着我们要完全复制和修改Phone生产管理的所有代码,显然这是一个笨办法,并不利于扩展和维护。
抽象工厂模式通过在AbstarctFactory中增加创建产品的接口,并在具体子工厂中实现新加产品的创建,当然前提是子工厂支持生产该产品。否则继承的这个接口可以什么也不干
类图
为了弄清楚上面的结构,我们使用具体的产品和工厂来表示上面的UML类图,能更加清晰的看出模式是如何演变的
新增PC接口
PC类
:定义PC产品的接口(AbstractPC)
public interface PC {
void make();
}
MiPC类
:定义小米电脑产品(MIPC)
public class MiPC implements PC {
public MiPC() {
this.make();
}
@Override
public void make() {
// TODO Auto-generated method stub
System.out.println("make xiaomi PC!");
}
}
MAC类
:定义苹果电脑产品(MAC)
public class MAC implements PC {
public MAC() {
this.make();
}
@Override
public void make() {
// TODO Auto-generated method stub
System.out.println("make MAC!");
}
}
修改相关接口,添加方法
AbstractFactory类
:增加PC产品制造接口
public interface AbstractFactory {
Phone makePhone();
PC makePC();
}
XiaoMiFactory类
:增加小米PC的制造(ConcreteFactory1)
public class XiaoMiFactory implements AbstractFactory{
@Override
public Phone makePhone() {
return new MiPhone();
}
@Override
public PC makePC() {
return new MiPC();
}
}
AppleFactory类
:增加苹果PC的制造(ConcreteFactory2)
public class AppleFactory implements AbstractFactory {
@Override
public Phone makePhone() {
return new IPhone();
}
@Override
public PC makePC() {
return new MAC();
}
}
演示:
public class Demo {
public static void main(String[] arg) {
AbstractFactory miFactory = new XiaoMiFactory();
AbstractFactory appleFactory = new AppleFactory();
miFactory.makePhone(); // make xiaomi phone!
miFactory.makePC(); // make xiaomi PC!
appleFactory.makePhone(); // make iphone!
appleFactory.makePC(); // make MAC!
}
}
工厂方法模式和抽象工厂模式总结
- 工厂方法模式:对单个产品
- 抽象工厂模式:对整个产品族,像例子中整个小米生态链
疑问:抽象工厂模式不会不符合开闭原则吗?如果新增一个产品,还是要修改原本的抽象工厂啊,emmmmmm是不是我还没理解透