当前位置: 首页 > news >正文

【GOF】三种工厂模式~

文章目录

  • 工厂模式
    • 1 简单工厂模式
      • 1.1 什么是简单工厂模式
      • 1.2 使用简单工厂模式与不使用简单工厂的对比
        • 1.2.1 不使用简单工厂模式
        • 1.2.2 使用简单工厂模式
      • 1.3 简单工厂的例子
      • 1.4 简单工厂的缺点
    • 2 工厂方法模式
      • 2.1 简介
      • 2.2 例子
        • 2.2.1 增加新品牌的汽车
      • 2.3 类图
      • 2.4 注意
    • 3 抽象工厂模式
      • 3.1 概念
      • 3.2 例子
      • 3.3 适用场景
      • 3.4 优缺点
          • 优点:
          • 缺点

工厂模式

作用:实现了创建者和调用者的分离

详细分类:

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

1 简单工厂模式

1.1 什么是简单工厂模式

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

简单工厂可以根据传入的参数不同,返回不同类的实例

简单工厂模式中,简单工厂类负责创建其他类的实例,其他类通常都具有共同的父类

1.2 使用简单工厂模式与不使用简单工厂的对比

1.2.1 不使用简单工厂模式

不使用简单工厂模式,用户需要自己new 所需要的实例,比如想要使用Tesla的属性,就必须得先创建(new)Tesla类,然后才可以使用Tesla属性。这意味着你需要了解一下实现类的内部(比如需不需要传参),如果用到的次数非常的对,就需要实例化很多次。image-20220929111223820

1.2.2 使用简单工厂模式

使用简单工厂模式,就不需要每次都实例化,只需要直接使用工厂的方法获取实例即可(简单工厂的方法是静态的,不需要new简单工厂,这也是为什么简单工厂模式又叫静态工厂方法

image-20220929112117797

1.3 简单工厂的例子

Car.interface

public interface Car {
    void name();
    void price();
}

Tesla.java

public class Tesla implements Car{
    @Override
    public void name() {
        System.out.println("特斯拉汽车");
    }

    @Override
    public void price() {
        System.out.println("¥500000");
    }
}

Wuling.java

public class WuLing implements Car{
    @Override
    public void name() {
        System.out.println("五菱宏光");
    }

    @Override
    public void price() {
        System.out.println("¥9999999");
    }
}

CarFactory.java

public class CarFactory {
    /* 生产五菱宏光 */
    public static WuLing productWuling()
    {
        return new WuLing();
    }
    /* 生产特斯拉 */
    public static Tesla productTesla()
    {
        return new Tesla();
    }
}

Customer.java

public class Customer {
    public static void main(String[] args) {
        Tesla tesla = CarFactory.productTesla();
        tesla.name();
        tesla.price();
    }
}

1.4 简单工厂的缺点

如果再增加一个车,就必须要改变CatFactory类,这违法了开闭原则。

所以,简单工厂模式对于产品角色的开-闭原则是成立的,对于工厂角色开-闭原则则是不成立的。简单工厂角色只在有限的程度上支持开闭原则。

2 工厂方法模式

2.1 简介

工厂方法模式是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂、具体工厂、抽象产品、具体产品。

工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(可以是抽象类和接口),这个类将不再负责具体的产品生产,而是只制定一些规范,具体的生产工作由其子类去完成。

2.2 例子

工厂方法模式对简单工厂模式做了一些改进,让简单工厂模式能够完全遵循开闭原则。

对1.3例子的优化

在1.3的基础上,将CarFactory分离出来,不是有一个大的工厂,而是每种汽车都有自己的工厂,生产产品,而每个汽车工厂遵循一定的规范。

简单工厂

image-20220929153012172

工厂方法模式

image-20220929153031612

Factory.interface

public interface Factory {
    public Car productCar();
}

TeslaFactory.java

public class TeslaFactory implements Factory{
    @Override
    public Car productCar() {
        return new Tesla();
    }
}

WulingFactory.java

public class WulingFactory implements Factory{
    @Override
    public Car productCar() {
        return new WuLing();
    }
}

这样Customer可以直接通过品牌汽车工厂生产相应品牌的汽车

Customer.java

public class Customer {
    public static void main(String[] args) {
        Car car = new TeslaFactory().productCar();
        car.name();
    }
}

image-20220929153449873

2.2.1 增加新品牌的汽车

这时候便不需要改动工厂Factory,只需要增加一个新的汽车工厂类DazongFactory和汽车类 Dazong

DaZongFactory.java

public class DaZongFactory implements Factory{
    @Override
    public Car productCar() {
        return new DaZong();
    }
}

DaZong.java

public class DaZong implements Car{
    @Override
    public void name() {
        System.out.println("大众汽车..");
    }

    @Override
    public void price() {
        System.out.println("¥88888888");
    }
}

2.3 类图

懒得画了,自动生成的,反正是增加汽车不会改变原有的代码和结构,没有违法开闭原则

image-20220929154159412

2.4 注意

但是在实际开发过程中,简单工厂模式用的更多,因为工厂方法模式虽然很好的保证了开闭原则,但是实现起来也复杂的多,所以我们基本上都使用简单工厂模式。

3 抽象工厂模式

3.1 概念

抽象工厂模式(Abstract Factory Pattern)隶属于设计模式中的创建型模式,用于产品族的构建。抽象工厂是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂是指当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象。

抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类

产品族::在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。如华为工厂可以生产华为产品包括:华为手机、华为路由器、华为电视

产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有华为电视机、小米电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。

image-20220929161809269

注意:横纵坐标的意思是,每一列的继承结构是产品等级结构,每一行代表的是一个产品族。

3.2 例子

针对上图,设计一个抽象工厂模式。

有三个产品等级结构:手机、电视、路由器

有三个产品族:华为、小米、TCL

为了简化操作每个产品只有打开和关闭两个功能。(emm…还是太多了,只写手机和电视)

类非常的多,但使用起来,感觉很不错

image-20220929164157813

Factory.interface

public interface Factory {
    public PhoneProduct productPhone();
    public TvProduct productTV();
}

产品族 就体现在以下的代码中,每个品牌的工厂可以生产自己品牌的所有产品

HuaweiFactory.java

public class HuaweiFactory implements Factory{
    @Override
    public PhoneProduct productPhone() {
        return new HuaWeiPhone();
    }

    @Override
    public TvProduct productTV() {
        return new HuaweiTv();
    }
}

XiaomiFactory.java


public class XiaomiFactory implements Factory{
    @Override
    public PhoneProduct productPhone() {
        return new XiaomiPhone();
    }

    @Override
    public TvProduct productTV() {
        return new XiaomiTv();
    }
}

TclFactory.java

public class TclFactory implements Factory{
    @Override
    public PhoneProduct productPhone() {
        return new TclPhone();
    }

    @Override
    public TvProduct productTV() {
        return new TclTv();
    }
}

PhoneProduct.interface

public interface PhoneProduct {
    public void open();
    public void close();
}

XiaomiPhone.java

public class XiaomiPhone implements PhoneProduct{
    @Override
    public void open() {
        System.out.println("打开小米手机.....");
    }

    @Override
    public void close() {
        System.out.println("关闭小米手机........");
    }
}

HuaWeiPhone.java

public class HuaWeiPhone implements PhoneProduct{
    @Override
    public void open() {
        System.out.println("打开华为手机.....");
    }

    @Override
    public void close() {
        System.out.println("关闭华为手机.....");

    }
}

TclPhone.java

public class TclPhone implements PhoneProduct{
    @Override
    public void open() {
        System.out.println("打开TCL手机");
    }

    @Override
    public void close() {
        System.out.println("关闭Tcl手机");
    }
}

上面这四个就体现了产品等级机构

image-20220929164801435

其他的就是照猫画虎…实在太多 不写了

Client.java

public class Client {
    public static void main(String[] args) {
        PhoneProduct phoneProduct = new HuaweiFactory().productPhone();
        phoneProduct.open();
        phoneProduct.close();
    }
}

image-20220929164845396

3.3 适用场景

  • 客户端(应用层)不依赖产品类实例如何被创建、实现等细节

  • 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复代码

  • 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现

3.4 优缺点

优点:
  • 具体产品在应用层的代码隔离,无需关心创建的细节
  • 将一个系列的产品统一到一起创建
缺点
  • 规定了所有可能被创建的产品集合,产品族中拓展新的产品困难。
  • 增加了系统的抽象性和理解难度。

相关文章:

  • 算法 |【实验5.2】1-深度优先搜索暴力求解旅行商问题
  • OpenCV-Python学习(2)—— OpenCV 图像的读取和显示
  • Unity技术手册-初识编辑器(上)
  • 基于Java+SpringBoot+vue+elementui图书商城系统设计实现
  • 电子病历结构化之实体识别(附完整项目代码)
  • 手写Spring——bean的扫描、加载和实例化
  • 【Vue】Vue的v-if、v-if-else、v-else-if、v-show的使用
  • 【设计模式】创建型模式:单例模式
  • Sentry、Loki 轻量级日志系统部署及应用
  • Spring Boot 统一功能处理
  • qsort:我很强,了解一下(详解过程)
  • 因为一道题,我把 try-catch-finally 的细节都整理了一遍(1500字)
  • 32、学习 Java 中的注解(参照官方教程)
  • 【第一部分 | HTML】1:揭露HTML的神秘面纱
  • 安装finalshell
  • 深入了解以太坊
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 2019年如何成为全栈工程师?
  • Apache Pulsar 2.1 重磅发布
  • co.js - 让异步代码同步化
  • codis proxy处理流程
  • Cookie 在前端中的实践
  • emacs初体验
  • PaddlePaddle-GitHub的正确打开姿势
  • passportjs 源码分析
  • storm drpc实例
  • 笨办法学C 练习34:动态数组
  • 从setTimeout-setInterval看JS线程
  • 记录一下第一次使用npm
  • 技术发展面试
  • 全栈开发——Linux
  • 如何编写一个可升级的智能合约
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 用Visual Studio开发以太坊智能合约
  • 从如何停掉 Promise 链说起
  • 函数计算新功能-----支持C#函数
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • ${ }的特别功能
  • (3)STL算法之搜索
  • (4)事件处理——(7)简单事件(Simple events)
  • (C#)获取字符编码的类
  • (C++)八皇后问题
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (小白学Java)Java简介和基本配置
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)http-server应用
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转)编辑寄语:因为爱心,所以美丽
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • (转载)虚函数剖析
  • .chm格式文件如何阅读
  • .FileZilla的使用和主动模式被动模式介绍
  • .form文件_一篇文章学会文件上传