概述
- 工厂模式(
简单工厂模式,工厂方法模式,抽象工厂模式)是23种设计模式中最常用的一种,属于设计模式中的创建型模式。 - 工厂模式是java面向接口编程的一种体现,我们在创建对象时不会对客户端暴露创建逻辑,而是通过抽象接口来创建对象,使用和创建分离,降低耦合度和方便扩展
- 工厂模式的应用场景很多,比如jdbc、spring ioc、spring aop、解析xml、Executors等等,实在是数不胜数,实际开发中,比如导出不同格式的报表、对接一些不同硬件厂商的接口等
简单工厂模式
/**
* 手机(抽象产品角色)
*/
public interface Phone {
//获取手机
void getPhone();
}
/**
* @date 2020/5/9 19:55
* @Author yz
* 华为手机实现类(具体产品角色)
*/
public class HuaweiPhone implements Phone{
@Override
public void getPhone() {
System.out.println("华为手机");
}
}
/**
* @date 2020/5/9 19:54
* @Author yz
* 小米手机实现类(具体产品角色)
*/
public class XiaomiPhone implements Phone{
@Override
public void getPhone() {
System.out.println("小米手机");
}
}
/**
* @date 2020/5/9 19:56
* @Author yz
* 手机工厂类(工厂角色)
*/
public class PhoneFactory {
/**
* 生产手机
*/
public Phone producePhone(String name){
Phone phone=null;
if("xiaomi".equals(name))
phone=new XiaomiPhone();
if("huawei".equals(name))
phone=new HuaweiPhone();
return phone;
}
}
public class Customer {
public static void main(String[] args) {
PhoneFactory phoneFactory=new PhoneFactory();
Phone xiaomi = phoneFactory.producePhone("xiaomi");
Phone huawei = phoneFactory.producePhone("huawei");
xiaomi.getPhone();
huawei.getPhone();
}
}
组成
- 工厂角色(PhoneFactory)
- 抽象产品角色(Phone)
- 多个具体产品角色(HuaweiPhone、XiaomiPhone)
应用
- 业务比较简单,实现类比较少
- 业务固定,基本不需要修改
- 调用者不需关心实现逻辑
优点
屏蔽实现,调用者不需要关心具体实现,封装性好, 解除耦合,方便业务扩展,当需要新的实现时,只需要增加实现类并修改工厂类即可
缺点
每增加一个实现类,就需要修改工厂类,这样就违背了开闭原则,而且当实现类过多时,也不易维护,工厂类会变得臃肿
工厂方法模式
/**
* 手机(抽象产品角色)
*/
public interface Phone {
//得到手机
void getPhone();
}
/**
* @date 2020/5/9 19:54
* @Author yz
* 小米手机实现类(具体产品角色)
*/
public class XiaomiPhone implements Phone {
@Override
public void getPhone() {
System.out.println("小米手机");
}
}
/**
* @date 2020/5/9 19:55
* @Author yz
* 华为手机实现类(具体产品角色)
*/
public class HuaweiPhone implements Phone {
@Override
public void getPhone() {
System.out.println("华为手机");
}
}
/**
* @date 2020/5/9 19:56
* @Author yz
* 手机工厂类(抽象工厂)
*/
public interface PhoneFactory {
/**
* 生产手机
*/
public Phone producePhone();
}
/**
* @date 2020/5/9 19:54
* @Author yz
* 小米手机工厂类(实例工厂)
*/
public class XiaomiPhoneFactory implements PhoneFactory {
@Override
public Phone producePhone() {
return new XiaomiPhone();
}
}
/**
* @date 2020/5/16 11:27
* @Author yz
* 华为手机工厂类(实例工厂)
*/
public class HuaweiPhoneFactory implements PhoneFactory {
@Override
public Phone producePhone() {
return new HuaweiPhone();
}
}
/**
* @date 2020/5/9 19:59
* @Author yz
* 客户类
*/
public class Customer {
public static void main(String[] args) {
PhoneFactory xiaomiPhoneFactory=new XiaomiPhoneFactory();
PhoneFactory huaweiPhoneFactory=new HuaweiPhoneFactory();
xiaomiPhoneFactory.producePhone().getPhone();
huaweiPhoneFactory.producePhone().getPhone();
}
}
组成
- 抽象工厂角色(PhoneFactory)
- 抽象产品角色(Phone)
- 多个具体产品角色(HuaweiPhone、XiaomiPhone)
- 多个具体工厂角色(HuaweiPhoneFactory、XiaomiPhoneFactory)
优点
符合单一职责,当增加新的实现时,无需修改代码,只需要增加新的产品和工厂即可,解决了简单工厂违背开闭原则的缺点。
缺点
每增加一个产品(实例类),就需要增加一个工厂类,容易使工厂类数量庞大,增加管理难度
抽象工厂方法
/**
* 手机(抽象产品角色)
*/
public interface Phone {
//生产
void getPhone();
}
/**
* @date 2020/5/9 19:54
* @Author yz
* 小米手机实现类(具体产品角色)
*/
public class XiaomiPhone implements Phone {
@Override
public void getPhone() {
System.out.println("小米手机");
}
}
/**
* @date 2020/5/9 19:55
* @Author yz
* 华为手机实现类(具体产品角色)
*/
public class HuaweiPhone implements Phone {
@Override
public void getPhone() {
System.out.println("华为手机");
}
}
/**
* 充电器(抽象产品角色)
*/
public interface Charger {
//得到充电器
void getCharger();
}
/**
* @date 2020/5/31 16:17
* @Author yz
* 小米充电器实现类(具体产品角色)
*/
public class XiaomiCharger implements Charger{
@Override
public void getCharger() {
System.out.println("小米充电器");
}
}
/**
* @date 2020/5/31 16:17
* @Author yz
* 华为充电器实现类(具体产品角色)
*/
public class HuaweiCharger implements Charger{
@Override
public void getCharger() {
System.out.println("华为充电器");
}
}
/**
* @date 2020/5/9 19:56
* @Author yz
* 电子产品工厂类(抽象工厂)
*/
public interface ElectronicFactory {
/**
* 得到手机
*/
public Phone producePhone();
/**
* 得到充电器
*/
public Charger produceCharger();
}
/**
* @date 2020/5/9 19:54
* @Author yz
* 小米工厂类(实例工厂)
*/
public class XiaomiFactory implements ElectronicFactory {
@Override
public Phone producePhone() {
return new XiaomiPhone();
}
@Override
public Charger produceCharger() {
return new XiaomiCharger();
}
}
/**
* @date 2020/5/16 11:27
* @Author yz
* 华为工厂类(实例工厂)
*/
public class HuaweiFactory implements ElectronicFactory {
@Override
public Phone producePhone() {
return new HuaweiPhone();
}
@Override
public Charger produceCharger() {
return new HuaweiCharger();
}
}
public class Customer {
public static void main(String[] args) {
ElectronicFactory xiaomiPhoneFactory=new XiaomiFactory();
ElectronicFactory huaweiPhoneFactory=new HuaweiFactory();
xiaomiPhoneFactory.producePhone().getPhone();
huaweiPhoneFactory.producePhone().getPhone();
xiaomiPhoneFactory.produceCharger().getCharger();
huaweiPhoneFactory.produceCharger().getCharger();
}
}
组成
- 抽象工厂角色(ElectronicFactory)
- 多个抽象产品角色(Phone、Charger)
- 多个具体产品角色(HuaweiPhone、XiaomiPhone、HuaweiCharger、XiaomiCharger)
- 多个具体工厂角色(HuaweiFactory、XiaomiFactory)
优点
符合开闭原则,增加产品族容易,只需要增加相应的产品和工厂即可,扩展性高。
缺点
当需要增加产品时,需要修改所有的所有的工厂类的方法(抽象工厂、实例工厂),违背了开闭原则
抽象工厂方法和工厂方法的区别
工厂方法模式: 一个抽象产品类,可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式: 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。 一个抽象工厂类,可以派生出多个具体工厂类。 每个具体工厂类可以创建多个具体产品类的实例。
区别: 工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。 工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
总结
三种方式各有优缺点,从结构复杂度和扩展性来看 抽象工厂>工厂方法>简单工厂,实际开发中,大部分都是用的简单工厂,工厂方法和抽象工厂用的比较少,工厂方法和抽象工厂,虽然增加了系统扩展性,但是修改起来,比简单工厂要麻烦。真正的高手是无招胜有招,武林高手不可能百分百按照招式来干架吧,结合业务来用,适合的才是最好的