在Java语言中,我们通常有以下几种创建对象的方式:
(1) 使用new关键字直接创建对象;
(2) 通过反射机制创建对象;
(3) 通过clone()方法创建对象;
(4) 通过工厂类创建对象(其实本质也是通过new关键字或者反射的方式创建实例对象)
为什么要用工厂模式
(1) 解耦 :把对象的创建和使用的过程分开。就是Class A 想调用 Class B ,那么A只是调用B的方法,而至于B的实例化,就交给工厂类。
(2)降低代码重复: 如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。
(3) 降低维护成本 :由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建对象B的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。
工厂模式可以分为三类
(1) 简单工厂模式(Simple Factory)
(2)工厂方法模式(Factory Method)
(3)抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。 GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。
简单工厂模式
简单工厂模中的角色
工厂(Factory)角色 :简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
抽象产品(Product)角色 :简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品(Concrete Product)角色:简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。
简单工厂示例
设计一个手机工厂,这个手机工厂可以同时生产华为手机、小米手机
抽象产品角色-手机接口
public interface Mobile {
public void createMobile();
}
具体产品角色-华为手机类
public class Huawei implements Mobile {
@Override
public void createMobile() {
System.out.println("生产华为手机");
}
}
具体产品角色-小米手机类
public class Xiaomi implements Mobile {
@Override
public void createMobile() {
System.out.println("生产小米手机");
}
}
工厂角色
public class MobileFactory {
public Mobile cretaeMobie(String type){
switch(type){
case "huawei":
return new Huawei();
case "xiaomi":
return new Xiaomi();
default:
break;
}
return null;
}
}
测试类
public class Customer {
public static void main(String[] args) {
MobileFactory mobileFactory = new MobileFactory();
Mobile huaweiMobile = mobileFactory.cretaeMobie("huawei");
huaweiMobile.createMobile();
Mobile xiaomiMobile = mobileFactory.cretaeMobie("xiaomi");
xiaomiMobile.createMobile();
}
}
简单工厂模式只有一个统一的工厂类,当新增一个类时,要在工厂类中增加相应的创建业务逻辑,这显然是违背开闭原则的,我们可以使用工厂方法模式进行优化
工厂方法模式
工厂方法模式中的角色
抽象工厂(Abstract Factory)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂(Concrete Factory)角色 :这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象。
抽象产品(AbstractProduct)角色 :工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品(Concrete Product)角色 :这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应
工厂方法模式示例
设计一个华为手机工厂,一个小米手机工厂,分别用来生产华为手机和小米手机
抽象产品角色
public interface Mobile {
public void createMobile();
}
具体产品角色-华为手机类
public class Huawei implements Mobile {
@Override
public void createMobile() {
System.out.println("生产华为手机");
}
}
具体产品角色-小米手机类
public class Xiaomi implements Mobile {
@Override
public void createMobile() {
System.out.println("生产小米手机");
}
}
抽象工厂角色
public interface AbstractFactory {
public Mobile createMobile();
}
具体工厂角色-华为手机工厂
public class HuaweiFactory implements AbstractFactory {
@Override
public Mobile createMobile() {
return new Huawei();
}
}
具体工厂角色-小米手机工厂
public class XiaomiFactory implements AbstractFactory {
@Override
public Mobile createMobile() {
return new Xiaomi();
}
}
测试方法
public class Customer {
public static void main(String[] args) {
HuaweiFactory huaweiFactory = new HuaweiFactory();
Mobile huawei = huaweiFactory.createMobile();
huawei.createMobile();
XiaomiFactory xiaomiFactory = new XiaomiFactory();
Mobile xiaomi = xiaomiFactory.createMobile();
xiaomi.createMobile();
}
}
在工厂方法模式中,我们使用某个工厂生产同一类产品,当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。抽象工厂模式是工厂方法的仅一步深化,在这个模式中的工厂类不单单可以创建一种产品,而是可以创建一组产品
抽象工厂模式
抽象工厂模式中的角色
抽象工厂(AbstractFactory)角色 :是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
具体工厂类(ConreteFactory)角色 :这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象。
抽象产品(Abstract Product)角色 :工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
具体产品(Concrete Product)角色 :抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。在抽象工厂中创建的产品属于同一产品族。
抽象工厂模式是工厂方法的仅一步深化,在这个模式中的工厂类不单单可以创建一个对象,而是可以创建一组对象。这是和工厂方法最大的不同点。
抽象工厂模式实例
设计工厂用来生产华为手机和小米手机,华为手机跟小米手机由不同的cpu和不同屏幕组成
抽象产品角色-cpu接口
public interface Cpu {
public void createCpu();
}
具体产品角色-麒麟cpu
public class KirinCpu implements Cpu {
@Override
public void createCpu() {
System.out.println("生产麒麟cpu");
}
}
具体产品角色-骁龙cpu
public class SnapdragonCpu implements Cpu {
@Override
public void createCpu() {
System.out.println("生产骁龙cpu");
}
}
抽象产品角色-屏幕接口
public interface Screen {
public void createScreen();
}
具体产品角色-三星屏幕
public class SamsungScreen implements Screen {
@Override
public void createScreen() {
System.out.println("生产三星屏幕");
}
}
具体产品角色-LG屏幕
public class LGScreen implements Screen{
@Override
public void createScreen() {
System.out.println("生产LG屏幕");
}
}
抽象工厂角色
public interface AbstractFactory {
public Cpu createCpu();
public Screen createScreen();
}
具体工厂角色-华为手机工厂
public class HuaweiFactory implements AbstractFactory {
@Override
public Cpu createCpu() {
return new KirinCpu();
}
@Override
public Screen createScreen() {
return new LGScreen();
}
}
具体工厂角色-小米手机工厂
public class XiaomiFactory implements AbstractFactory{
@Override
public Cpu createCpu() {
return new SnapdragonCpu();
}
@Override
public Screen createScreen() {
return new SamsungScreen();
}
}
测试类
public class Customer {
public static void main(String[] args) {
HuaweiFactory huaweiFactory = new HuaweiFactory();
Cpu huaweiCpu = huaweiFactory.createCpu();
huaweiCpu.createCpu();
Screen huaweiScreen = huaweiFactory.createScreen();
huaweiScreen.createScreen();
XiaomiFactory xiaomiFactory = new XiaomiFactory();
Cpu xiaomiCpu = xiaomiFactory.createCpu();
xiaomiCpu.createCpu();
Screen xiaomiScreen = xiaomiFactory.createScreen();
xiaomiScreen.createScreen();
}
}
抽象工厂的工厂和工厂方法的区别:
厂方法模式中的工厂只生产单一的产品,而抽象工厂模式中的工厂生产多个产品,工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
工厂模式适用的一些场景
(1)对象的创建过程/实例化准备工作很复杂,需要初始化很多参数、查询数据库等。
(2)类本身有好多子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变。
(3)客户端不需要知道它所创建的对象的类,只知道创建它的工厂名就完成了创建过程。