设计模式之工厂模式

一、什么是工厂模式

工厂模式属于创建型模式,简单来说就是把类的实例化交给工厂类来完成,被创建的类对象通常要继承共同的父类或实现共同的接口。

二、为什么使用工厂模式

  • 耦合性:客户端不需要知道大量具体产品类创建的细节,将产品类对象的创建和使用分开,降低耦合,只需要通过工厂类返回产品类对象就可以了。
  • 复用性:需要在多个客户端使用具体产品实例对象的,通过工厂类统一进行实例化,大大提高了代码复用性。
  • 可维护性:随着业务变化,新增产品类型,只要更新工厂类就可以了,对于之前客户端调用是透明的。

三、工厂模式分类

  • 简单工厂模式:适用场景:涉及的类对象比较少,只需要一个工厂类就可以管理创建具体产品类对象。客户端只需要知道具体对象的参数就可以返回对应的对象实例。比如:小米手机系列,包括红米、小米等品牌。
  • 工厂方法模式:定义一个用于创建产品对象的工厂接口,让子类决定实例化哪个产品对象。工厂方法使一个产品类的时候延迟到其工厂的子类。
  • 抽象工厂模式:官方定义:是一种为访问类提供一个创建一组相关或相互依赖的接口,且访问类无须指定所要产品的具体类就能够得到同族的不同等级的产品的模式结构。

抽象工厂模式是工厂方法模式的升级版,工厂方法模式适用于生产一个等级的产品,而抽象工厂模式则适用于生产多个等级(产品族)的产品。

如下图产品等级与产品族区别示意图:

设计模式之工厂模式插图

四、工厂模式UML类图

1、简单工厂模式

设计模式之工厂模式插图2

2、工厂方法模式

设计模式之工厂模式插图4

3、抽象工厂模式

设计模式之工厂模式插图6

五、工厂模式角色

1、简单工厂模式角色

  • 工厂类(phoneFactory):负责创建具体产品类的实例对象,直接提供给客户端使用,根据具体产品参数返回对应实例对象。
  • 抽象产品类(IPhone):是被创建类的父类,负责定义需要具体产品类的抽象方法。
  • 具体产品类(XiamiPhone):具体的产品类,继承了父类实现了具体功能,由工厂类负责对其进行实例化。

2、工厂方法模式角色

  • 抽象工厂(IPhoneFactory):提供了创建产品的接口,调用者通过访问具体工厂的工厂方法来创建产品。
  • 具体工厂(XiaoMiPhoneFactory):主要是实现抽象工厂中的抽象方法 ,完成具体产品的创建。
  • 抽象产品(IPhone):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(XiaomiPhone):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

3、抽象工厂模式角色

  • 抽象工厂:提供了创建产品的接口,调用者通过访问具体工厂的工厂方法来创建产品。
  • 具体工厂:主要是实现抽象工厂中的抽象方法 ,完成具体产品的创建。
  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

六、工厂模式优缺点

1、简单工厂模式

1)缺点

  1. 违反了最重要的OCP(对修改关闭,对扩展开放)原则,比如当新增一个手机品牌时,对应PhoneFactory也需要进行修改。

2、工厂方法模式

1)优点

  1. 调用方只需要制定具体工厂的名称就可得到所需要的产品,无须知道产品的具体创建过程;
  2. 在系统增加新的产品时,只需要添加产品类和对应的具体工厂类,无须对原有工厂进行任何修改,满足开闭原则。

2)缺点

  1. 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,增加了系统的复杂度,当产品比较多时,就会产生“工厂类爆炸”。

3、抽象工厂模式

1)优点

  1. 由于工厂模式是工厂方法模式的升级版,因此兼具了工厂模式的优点。
  2. 可以对产品族中相关联的多等级产品进行共同管理。
  3. 当新增一个产品族时,不需要修改原代码,满足开闭原则。

2)缺点

  1. 当产品族中需要增加一个新的产品时,所有的工厂类都要进行修改。

七、工厂模式demo示例

1、Demo需求

以两个产品族:小米工厂(生产小米手机、小米电视),华为工厂(生产华为手机,华为电视)为例。

2、简单工厂模式

/**
  * 手机品牌接口
  */ public interface IPhone {

     /**
      * 销售的手机品牌
      */     void sale();
 }
/**
  * 具体产品-小米品牌手机
  */ public class XiaomiPhone implements IPhone {

     public void sale() {
         System.out.println("我是小米手机");
     }
 }
/**
  * 具体产品-红米品牌手机
  */ public class HongmiPhone implements IPhone{

     public void sale() {
         System.out.println("我是红米手机");
     }
 }
/**
  * 简单工厂类
  */ public class PhoneFactory {
 
     public static IPhone salePhone(String brandType){
         if("xiaomi".equals(brandType)){
             return new XiaomiPhone();
         }else if ("hongmi".equals(brandType)){
             return new HongmiPhone();
         }
         return null;
     }
 }
public class ClientPhoneTest {

     public static void main(String[] args) {
         IPhone phone = PhoneFactory.salePhone("xiaomi");
         phone.sale();
         phone = PhoneFactory.salePhone("hongmi");
         phone.sale();
     }
 }

控制台输出日志:

我是小米手机
我是红米手机

3、工厂方法模式

/**
  * 产品接口:手机
  */ public interface IPhone {
 
     void makePhone();
 }
/**
  * 具体产品:小米手机
  */ public class XiaomiPhone implements IPhone {

     public void makePhone() {
         System.out.println("生产小米手机。。。");
     }
 }
/**
  * 具体产品:华为手机
  */ public class HuaweiPhone implements IPhone{

     public void makePhone() {
         System.out.println("生产华为手机。。。");
     }
 }
 /**
  * 工厂接口:手机工厂
  */ public interface IPhoneFactory {
 
     IPhone makePhone();
 }
/**
  * 具体工厂子类:华为手机工厂类
  */ public class HuaweiPhoneFactory implements IPhoneFactory{

     public IPhone makePhone() {
         return new HuaweiPhone();
     }
 }
/**
  * 具体工厂子类:小米手机工厂类
  */ public class XiaomiPhoneFactory implements IPhoneFactory {

     public IPhone makePhone() {
         return new XiaomiPhone();
     }
 }
 /**
  * 客户端测试
  */ public class ClientFactoryMethodTest {

     public static void main(String[] args) {
         //通过小米工厂创建小米手机对象
         IPhoneFactory phoneFactory = new XiaomiPhoneFactory();
         IPhone iPhone = phoneFactory.makePhone();
         iPhone.makePhone();
 
         //通过华为手机工厂创建华为手机对象
         phoneFactory = new HuaweiPhoneFactory();
         IPhone iPhone1 = phoneFactory.makePhone();
         iPhone1.makePhone();
     }
 }

4、抽象工厂模式

/**
  * 产品接口:手机
  */ public interface IPhone {
 
     void makePhone();
 }
/**
  * 具体产品:小米手机
  */ public class XiaomiPhone implements IPhone {

     public void makePhone() {
         System.out.println("生产小米手机。。。");
     }
 }
/**
  * 具体产品:华为手机
  */ public class HuaweiPhone implements IPhone{

     public void makePhone() {
         System.out.println("生产华为手机。。。");
     }
 }
/**
  * 电视产品接口
  */ public interface ITV {

     void makeTV();
 }
/**
  * 具体产品:华为电视
  */ public class HuaweiTV implements ITV {

     public void makeTV() {
         System.out.println("生产华为电视。。。");
     }
 }
/**
  * 具体产品:小米电视
  */ public class XiaomiTV implements ITV {

     public void makeTV() {
         System.out.println("生产小米电视。。。");
     }
 }
/**
  * 抽象工厂接口:多等级(手机产品、电视产品)产品工厂接口
  */ public interface IProductFactory {

     IPhone createPhone();
     ITV createTV();
 }
 /**
  * 具体工厂实现:华为工厂产品族
  */ public class HuaweiProductFactory implements IProductFactory {

     public IPhone createPhone() {
         return new HuaweiPhone();
     }
 
     public ITV createTV() {
         return new HuaweiTV();
     }
 }
/**
  * 具体工厂:小米工厂产品族
  */ public class XiaomiProductFactory implements IProductFactory {

     public IPhone createPhone() {
         return new XiaomiPhone();
     }
 
     public ITV createTV() {
         return new XiaomiTV();
     }
 }
/**
  * 测试客户端
  */ public class ClientAbstractFactoryTest {

     public static void main(String[] args) {
         IProductFactory productFactory = new HuaweiProductFactory();
         productFactory.createPhone().makePhone();
         productFactory.createTV().makeTV();
         productFactory = new XiaomiProductFactory();
         productFactory.createPhone().makePhone();
         productFactory.createTV().makeTV();
     }
 }

发表评论