工厂模式

  • 实现创建者与调用者的分离

以化妆品为例

  • 生产者:

    • 一个接口,提供了生产化妆品的方法

    public interface Cosmetics {
       void productCosmetics();
    }
  • 生产的对象:

    • 口红

      public class Lipstick implements Cosmetics{

         public void productCosmetics() {
             System.out.println("口红");
        }
      }
    • 眼影

      public class EyeShadow implements Cosmetics{

         public void productCosmetics() {
             System.out.println("眼影");
        }
      }
     

1、传统的方式

图解

设计模式之工厂模式-LMLPHP

  • 消费者

    • 消费者要首先把 Lipstick 和 EyeShadow 实例化(new),才能实现对象的方法。

    public class Consumer {
       public static void main(String[] args) {

           Cosmetics lipstick = new Lipstick();
           Cosmetics eyeShadow = new EyeShadow();

           lipstick.productCosmetics();
           eyeShadow.productCosmetics();
      }
    }

 

2、工厂模式(静态工厂模式)

图解

设计模式之工厂模式-LMLPHP

  • 化妆品工厂

    public class CosmeticsFactory {
       public static Cosmetics getCosmeticsFactory(String factory){
           if (factory.equals("口红")){
               return new Lipstick();
          }else if (factory.equals("眼影")){
               return new EyeShadow();
          }else {
               return null;
          }
      }
    }
  • 消费者

    • 通过化妆品工厂来得到对象的实例化,无需new,来实现对象的方法

    public class Consumer {
       public static void main(String[] args) {

           Cosmetics lipstick = CosmeticsFactory.getCosmeticsFactory("口红");
           lipstick.productCosmetics();

           Cosmetics eyeShadow = CosmeticsFactory.getCosmeticsFactory("眼影");
           eyeShadow.productCosmetics();
      }
    }
  • 工厂模式缺点:

    OOP七大原则之开闭原则:一个软件的实体应对扩展开放,对修改关闭

    工厂模式实现不了开闭原则,如果要扩展新的功能,必须修改CosmeticsFactory才能实现

 

3、工厂方法模式

  • 解决工厂模式无法实现开闭原则的问题

图解

设计模式之工厂模式-LMLPHP

  • 化妆品工厂

    public interface CosmeticsFactory {
       Cosmetics getCosmetics();
    }
  • 口红工厂

    public class LipstickFactory implements CosmeticsFactory {
       public Cosmetics getCosmetics() {
           return new Lipstick();
      }
    }
  • 眼影工厂

    public class EyeShadowFactory implements CosmeticsFactory {
       public Cosmetics getCosmetics() {
           return new EyeShadow();
      }
    }
  • 消费者

    public class Consumer {
       public static void main(String[] args) {

           Cosmetics lipstick = new LipstickFactory().getCosmetics();
           lipstick.productCosmetics();

           Cosmetics eyeShadow = new EyeShadowFactory().getCosmetics();
           eyeShadow.productCosmetics();
      }
    }
  • 新增一个产品:

    只需要编写一个产品类,例如眉笔,编写一个眉笔工厂继承化妆品工厂,

    可在不改动原有代码的基础上扩展功能,实现开闭原则。

 

4、抽象工厂模式

  • 简单工厂模式 和 工厂方法模式 都是用来生产同一等级结构的任意产品

    抽象工厂模式 统一创建同一系列的产品,可以创建多个产品家族的多个等级结构的产品

设计模式之工厂模式-LMLPHP

图解

设计模式之工厂模式-LMLPHP

实现

  • 产品工厂:

    public interface ProductFactory {

       //生产手机
       Phone productPhone();
       //生产电脑
       Computer productComputer();
    }
  • 手机:

    public interface Phone {

       //生产手机屏
       void productMobileScreen();
       //生产手机外壳
       void productPhoneShell();
       //生产手机套
       void productPhoneSet();
    }
  • 电脑:

    public interface Computer {

       //生产电脑屏
       void productMobileScreen();
       //生产电脑外壳
       void productPhoneShell();
       //生产电脑套
       void productPhoneSet();
    }
  • HUAWEI产品工厂:

    public class HUAWEIProductFactory implements ProductFactory {
       //实例化HUAWEI手机
       public Phone productPhone() {
           return new HUAWEIPhone();
      }

       //实例化HUAWEI电脑
       public Computer productComputer() {
           return new HUAWEIComputer();
      }
    }
  • ASUS产品工厂:

    public class ASUSProductFactory implements ProductFactory {

       //实例化ASUS手机
       public Phone productPhone() {
           return new ASUSPhone();
      }

       //实例化ASUS电脑
       public Computer productComputer() {
           return new ASUSComputer();
      }
    }
  • HUAWEI手机:

    public class HUAWEIPhone implements Phone {
       public void productMobileScreen() {
           System.out.println("生产HUAWEI手机屏");
      }

       public void productPhoneShell() {
           System.out.println("生产HUAWEI手机外壳");
      }

       public void productPhoneSet() {
           System.out.println("生产HUAWEI手机套");
      }
    }
  • ASUS手机:

    public class ASUSPhone implements Phone {
       public void productMobileScreen() {
           System.out.println("生产ASUS手机屏");
      }

       public void productPhoneShell() {
           System.out.println("生产ASUS手机外壳");
      }

       public void productPhoneSet() {
           System.out.println("生产ASUS手机套");
      }
    }
  • HUAWEI电脑:

    public class HUAWEIComputer implements Computer {
       public void productMobileScreen() {
           System.out.println("生产HUAWEI电脑屏");
      }

       public void productPhoneShell() {
           System.out.println("生产HUAWEI电脑外壳");
      }

       public void productPhoneSet() {
           System.out.println("生产HUAWEI电脑套");
      }
    }
  • ASUS电脑:

    public class ASUSComputer implements Computer {
       public void productMobileScreen() {
           System.out.println("生产ASUS电脑屏");
      }

       public void productPhoneShell() {
           System.out.println("生产ASUS电脑外壳");
      }

       public void productPhoneSet() {
           System.out.println("生产ASUS电脑套");
      }
    }
  • 消费者:

    public class Consumer {
       public static void main(String[] args) {

           //消费者直接操作HUAWEI和ASUS的产品工厂
           HUAWEIProductFactory huaweiProductFactory = new HUAWEIProductFactory();
           ASUSProductFactory asusProductFactory = new ASUSProductFactory();
           
           //通过工厂生产手机和电脑
           //huawei电脑
           Computer huaweiComputer = huaweiProductFactory.productComputer();
           //asus手机
           Phone asusPhone = asusProductFactory.productPhone();
           
           //调用生产的手机和电脑中的方法,操作手机和电脑
           huaweiComputer.productMobileScreen();
           huaweiComputer.productPhoneShell();
           
           asusPhone.productPhoneShell();
           asusPhone.productPhoneSet();
      }
    }
  • 优点:

    具体产品在应用层的代码隔离,无需关心创建的细节

    将同一系列的产品统一到一起创建

  • 缺点:

    产品簇中扩展新的产品困难

    增加了系统的抽象性和理解难度

 

5、小结

  • 简单工厂模式

    • 虽然没有实现开闭原则,但实际使用最多

  • 工厂方法模式

    • 不修改已有类的前提下,可以增加新的工厂类进行扩展

  • 抽象工厂模式

    • 不可以增加产品,可以增加产品族

  • 三种模式对比

    • 代码复杂度:简单工厂模式 < 工厂方法模式 < 抽象工厂模式

    • 结构复杂度:简单工厂模式 < 工厂方法模式 < 抽象工厂模式

    • 编程复杂度:简单工厂模式 < 工厂方法模式 < 抽象工厂模式

    • 管理复杂度:简单工厂模式 < 工厂方法模式 < 抽象工厂模式

  • 根据设计原则,应使用工厂方法模式

    根据实际业务,工厂方法模式使用最多

  • 工厂模式应用场景:

    • JDK中的Calenda的getInstance()方法

    • JDBC中的Connection对象的获取

    • Spring中IOC容器创建管理bean对象

    • 反射中Class对象的newInstance()方法

05-09 07:45