设计模式——工厂模式(包含:简单工厂模式、工厂方法模式、抽象工厂模式)

 相关链接:

【设计模式】专栏:【设计模式】专栏

相关例子代码可下载: Java常用设计模式例子

简介

目前工厂模式大致分为3种,分别是:

  1. 简单工厂模式

  2. 工厂方法模式

  3. 抽象工厂模式

简单工厂模式

简单工厂模式(Simple Factory Pattern)是属于创建型模式,又叫做静态工厂方法(Static Factory Method Pattern)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

作用:

将“类实例化”的操作和“使用对象”的操作分开,让使用者不用知道具体参数就可以实例化所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。

主要角色

具体工厂(Creator)角色

简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需要的产品对象。

抽象产品(Product)角色

简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。

具体产品(Concrete Product)角色

简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。

 

举个栗子:

假设有一台饮料机(工厂),可以调出各种口味的饮料(抽象产品),有三个按钮(参数)对应这三种饮料(具体产品)。这时候你可以根据点击按钮来选择你喜欢的饮料。

抽象产品:Product.java

/**
 * 简单工厂模式——抽象产品
 * 说明:
 * 描述产品的公共接口
 *
 */
public abstract class Product {
    /**
     * 产品介绍
     */
    public abstract void introduce();
}

具体产品: CocoProduct.java  、 MilkProduct.java 、 CofficeProduct.java

/**
 * 简单工厂模式——具体产品 A
 *
 * (可以看成是一种饮料:可乐)
 *
 */
public class CocoProduct extends Product{

    @Override
    public void introduce() {
        System.out.println("可乐");
    }
}


/**
 * 简单工厂模式——具体产品 B
 *
 *(可以看成是一种饮料:奶茶)
 *
 */
public class MilkProduct extends Product{

    @Override
    public void introduce() {
        System.out.println("奶茶");
    }
}


/**
 * 简单工厂模式——具体产品 C
 *
 * (可以看成是一种饮料:咖啡)
 *
 */
public class CofficeProduct extends Product{

    @Override
    public void introduce() {
        System.out.println("咖啡");
    }
}

具体工厂:SimpleFactory.java

/**
 * 简单工厂模式——具体工厂
 * 
 * 负责实现创建所有实例的内部逻辑,并提供一个外接调用的方法,创建所需的产品对象
 *
 */
public class SimpleFactory {

    /**
     * 提供给外接调用的方法
     * (可以看成是对外提供的三个小按钮)
     *
     * @param type 产品类型
     * @return FactoryPattern.SimpleFactoryPattern.Product
     */
    public static Product getProduct(String type) {
        switch (type) {
            case "coco":
                return new CocoProduct();
            case "milk":
                return new MilkProduct();
            case "coffice":
                return new CofficeProduct();
            default:
                return null;
        }
    }

}

测试:SimpleFactoryDemo.java

/**
 * 简单工厂模式
 *
 */
public class SimpleFactoryDemo {

    public static void main(String[] args) {
        // 创建具体的工厂
        SimpleFactory factory = new SimpleFactory();
        // 根据传入的参数生产不同的产品实例
        // (按下不同的按钮,获取饮料)
        Product coco = SimpleFactory.getProduct("coco");
        coco.introduce();
        Product milk = SimpleFactory.getProduct("milk");
        milk.introduce();
        Product coffice = SimpleFactory.getProduct("coffice");
        coffice.introduce();
    }

}

 

根据栗子可以描述为:

  • 一个抽象产品类,可以派生出多个具体产品类

  • 一个具体工厂类,通过往此工厂的static方法中传入不同参数,产出不同的具体产品类实例

优缺点

优点

  • 将创建、使用工作分开,不必关心类对象如何创建,实现了解耦

  • 把初始化实例时的工作放到工厂里进行,使代码更容易维护。更符合面向对象的原则&面向接口编程,而不是面向实现编程

缺点

  • 工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响

  • 违背“开放-关闭”原则,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂

  • 简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成

工厂方法模式

工厂方法模式,又称工厂模式(Factory Pattern)、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。(常用!)

作用:

将类的实例化(具体产品的创建)延迟到工厂类的子类(具体工厂)中完成,即由子类来决定应该实例化(创建)哪一个类。

主要角色

抽象工厂(Abstract Factory)角色

描述具体工厂的公共接口。

具体工厂(Concrete Factory)角色

描述具体工厂,创建产品的实例,供外界调用,主要实现了抽象工厂中的抽象方法,完成具体产品的创建。

抽象产品(Product)角色

负责描述产品的公共接口,定义了产品的规范,描述了产品的主要特性和功能。

具体产品(Concrete Product)角色

描述生产的具体产品,实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

 

举个栗子:

假设有各类的饮料机(抽象工厂),可以调出各种的饮料(抽象产品)。但是一类饮料机(具体工厂),只能生产一种饮料(具体产品)。如果你需要喝可乐,就需要买可乐饮料机。

抽象产品:Product.java

/**
 * 工厂方法模式——抽象产品
 *
 */
public abstract class Product {
    /**
     * 产品介绍
     */
    public abstract void introduce();
}

具体产品:ProductA.java 、ProductB.java

/**
 * 工厂方法模式——具体产品A
 *
 */
public class ProductA extends Product{
    @Override
    public void introduce() {
        System.out.println("饮料A");
    }
}


/**
 * 工厂方法模式——具体产品B
 *
 */
public class ProductB extends Product{
    @Override
    public void introduce() {
        System.out.println("饮料B");
    }
}

抽象工厂:Factory.java

/**
 * 工厂方法模式——抽象工厂
 *
 */
public abstract class Factory {
    /**
     * 生产产品
     *
     * @return FactoryPattern.FactoryPattern.Product
     */
    public abstract Product getProduct();
}

具体工厂:FactoryA.java 、FactoryB.java

/**
 * 工厂方法模式——具体工厂A
 *
 * (负责具体的产品A生产)
 *
 */
public class FactoryA extends Factory{
    @Override
    public Product getProduct() {
        return new ProductA();
    }
}


/**
 * 工厂方法模式——具体工厂B
 *
 * (负责具体的产品B生产)
 *
 */
public class FactoryB extends Factory{
    @Override
    public Product getProduct() {
        return new ProductB();
    }
}

测试:FactoryDemo.java

/**
 * 工厂方法模式
 *
 */
public class FactoryDemo {

    public static void main(String[] args) {
        // 创建具体的工厂
        FactoryA factoryA = new FactoryA();
        // 生产相对应的产品
        factoryA.getProduct().introduce();
        FactoryB factoryB = new FactoryB();
        factoryB.getProduct().introduce();
    }

}

 

根据栗子可以描述为

  • 一个抽象产品类,可以派生出多个具体产品类

  • 一个抽象工厂类,可以派生出多个具体工厂类

  • 每个具体工厂类只能创建一个具体产品类的实例

优缺点

优点

  • 符合“开-闭原则”,扩展性高:新增一种产品时,只需要增加相应的具体产品类和相应的工厂子类即可

  • 符合单一职责原则:每个具体工厂类只负责创建对应的产品

缺点

  • 增加了系统的复杂度:类的个数将成对增加

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

  • 一个具体工厂只能创建一种具体产品

抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。

抽象工厂模式工厂方法模式 最大的区别:

  • 抽象工厂中,每个工厂可以创建多种类的产品
  • 工厂方法中,每个工厂只能创建一类产品

作用

允许使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,这样就可以从具体产品中被解耦。

主要角色

抽象工厂(Abstract Factory)角色

描述具体工厂的公共接口

具体工厂(Concrete Factory)角色

描述具体工厂,创建产品的实例,供外界调用

抽象产品族(Abstract Product)角色

描述抽象产品的公共接口

抽象产品(Product)角色

描述具体产品的公共接口

具体产品(Concrete Product)角色

描述生产的具体产品

 

举个栗子:

假设有各类的自动售卖机(抽象工厂),可以出售各类食品(抽象产品族)。

有饮料、零食(抽象产品),比如常见的零售售卖机(具体工厂),出售矿泉水与面包(具体产品)。

抽象产品族:Product.java

/**
 * 抽象工厂模式——抽象产品族(食品)
 *
 */
public abstract class Product {
    /**
     * 产品介绍
     */
    public abstract void introduce();
}

抽象产品:ProductA.java、ProductB.java

/**
 * 抽象工厂模式——抽象产品(饮料)
 *
 */
public abstract class ProductA extends Product{
}


/**
 * 抽象工厂模式——抽象产品(零食)
 *
 */
public abstract class ProductB extends Product{
}

具体产品:ProductAa.java、ProductBb.java

/**
 * 抽象工厂模式——具体产品
 *
 */
public class ProductAa extends ProductA{
    @Override
    public void introduce() {
        System.out.println("矿泉水");
    }
}


/**
 * 抽象工厂模式——具体产品
 *
 */
public class ProductBb extends ProductB{
    @Override
    public void introduce() {
        System.out.println("面包");
    }
}

抽象工厂:AbstractFactory.java

/**
 * 抽象工厂模式——抽象工厂
 *
 */
public abstract class AbstractFactory {
    /**
     * 生产饮料
     */
    public abstract Product getProductA();
    /**
     * 生产零食
     */
    public abstract Product getProductB();
}

具体工厂:AbstractFactoryA.java

/**
 * 抽象工厂模式——具体工厂
 *
 * 负责具体的A类产品生产
 *
 */
public class AbstractFactoryA extends AbstractFactory{
    @Override
    public Product getProductA() {
        // 生产矿泉水
        return new ProductAa();
    }

    @Override
    public Product getProductB() {
        // 生产面包
        return new ProductBb();
    }
}

测试:AbstractFactoryDemo.java

/**
 * 抽象工厂模式
 *
 */
public class AbstractFactoryDemo {

    public static void main(String[] args) {
        // 创建零食售卖机(具体工厂)
        AbstractFactoryA abstractFactoryA = new AbstractFactoryA();
        // 获取矿泉水与面包(具体产品)
        abstractFactoryA.getProductA().introduce();
        abstractFactoryA.getProductB().introduce();
    }

}

 

根据实例可以描述为:

  • 多个抽象产品类,每个抽象产品可以派生出多个具体产品类

  • 一个抽象工厂类,可以派生出多个具体工厂类

  • 每个具体工厂类可以创建多个 具体产品类的实例

优缺点

优点

  • 降低耦合

  • 符合“开-闭原则”

  • 符合单一职责原则

  • 不使用静态工厂方法,可以形成基于继承的等级结构

  • 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点

  • 难以扩展新种类产品,要增加一个系列的某一产品,既要在抽象产品里加代码,又要在具体的里面加代码。

结束语

1、更多设计模式内容请看【设计模式】专栏

2、相关例子代码可下载: Java常用设计模式例子

PS:  【 Java常用设计模式例子 】 内已包含 【设计模式】专栏 里涉及的代码,如果之前已下载过的同学,就不需要重复下载啦~

以上内容如有不正确或需要补充的地方,还请多多请教,会及时更新改正~

欢迎评论~ 感谢点赞~

猜你喜欢

转载自blog.csdn.net/pjymyself/article/details/121931718