设计模式第二天|设计模式创建型:工厂模式、抽象工厂模式、单例模式、建造者模式

news2024/11/22 20:32:19

文章目录

  • 设计模式的分类
  • 工厂模式
    • 简单工厂
      • 定义
      • 核心
      • 俗话说
      • 优点
      • 缺点
      • 具体实现
    • 工厂模式(Spring IOC控制反转)
      • 定义
      • 核心
      • **组成**
      • **俗话说**
      • **实现思路**
      • **具体实现**
      • **使用场景**
  • 抽象工厂模式
    • **前提概念**
    • **定义**
    • **缺点**
    • **具体实现**
  • 单例模式
    • **定义**
    • **俗话说**
    • **特点**
    • **作用**
    • **分类**
    • **原理**
  • 建造者模式
    • 定义
    • **优点**
    • **缺点**
    • **角色组成**
    • 应用场景
    • 代码实现
    • 总结

设计模式的分类

总的来说设计模式分为三大类

  1. 创建型模式(五种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。
  2. 结构型模式(七种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
  3. 行为型模式(十一种):策略模式,模板方法模式,观察者模式,迭代子模式,责任链模式,命令模式,备忘录模式,状态模式,访问者模式,中介者模式,解释器模式。

这篇我们主要讲一下创建型模式。

由于我是java开发者,我会根据设计模式在java中的应用来说说。

工厂模式

简单工厂

定义

简单工厂模式其实并不算是一种设计模式,更多的时候是一种编程习惯。简单工厂的实现思路是,定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。

核心

为工厂类传入不同的type可以new不同的形状,返回结果为Shape 类型,这个就是简单工厂核心的地方了。

俗话说

现在有一个车间(工厂),由于需求比较少,所以一个车间可以生产不同的但是相像产品(具体对象),这些对象都是从一个模子里刻出来的(抽象对象)

优点

实现了对象创建和使用的职责分离,客户端不需知道所创建的具体产品类的类名以及创建过程,只需知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。

缺点

在于不符合“开闭原则”,每次添加新产品就需要修改工厂类。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

具体实现

class ShapeFactory {
          public static Shape getShape(String type) {
              Shape shape = null;
              if (type.equalsIgnoreCase("circle")) {
                  shape = new CircleShape();
              } else if (type.equalsIgnoreCase("rect")) {
                  shape = new RectShape();
              } else if (type.equalsIgnoreCase("triangle")) {
                  shape = new TriangleShape();
              }
              return shape;
          }
   }

工厂模式(Spring IOC控制反转)

工厂模式的作用就是创建对象

定义

工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。

核心

也就是说每个对象都有一个与之对应的工厂。

组成

  1. AbstractFactory(抽象工厂):声明了一组用于创建对象的方法,注意是一组。
  2. ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建对象的方法,生成一组具体对象。
  3. AbstractProduct(抽象产品):它为每种对象声明接口,在其中声明了对象所具有的业务方法。
  4. ConcreteProduct(具体产品):它定义具体工厂生产的具体对象。

俗话说

有好多车间,由于需求比较多,所以需要不同的车间来生产不同的商品,这些车间(具体工厂)生产的产品(具体对象)都是单一的,提高效率,这些车间都是一个车间模子(抽象工厂)里刻出来的,产品也是一个模子(抽象对象)里刻出来的.

实现思路

工厂方法的实现思路是,定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。

具体实现

就是将对象的具体创建交给工厂

  1. 产品类
//抽象产品
abstract class BMW {
	public BMW(){}
}
//具体产品
public class BMW320 extends BMW {
	public BMW320() {
		System.out.println("制造-->BMW320");
	}
}
//具体产品
public class BMW523 extends BMW{
	public BMW523(){
		System.out.println("制造-->BMW523");
	}
}
  1. 工厂类
//抽象工厂
interface FactoryBMW {
	BMW createBMW();
}
//具体工厂
public class FactoryBMW320 implements FactoryBMW{
 
	@Override
	public BMW320 createBMW() {
		return new BMW320();
	}
}
//具体工厂
public class FactoryBMW523 implements FactoryBMW {
	@Override
	public BMW523 createBMW() {
		return new BMW523();
	}
}
  1. 客户类(创建对象)
public class Customer {
	public static void main(String[] args) {
		FactoryBMW320 factoryBMW320 = new FactoryBMW320();
		BMW320 bmw320 = factoryBMW320.createBMW();
 
		FactoryBMW523 factoryBMW523 = new FactoryBMW523();
		BMW523 bmw523 = factoryBMW523.createBMW();
	}
}

使用场景

  1. 客户端不需要知道它所创建的对象的类
  2. 客户端可以通过子类来指定创建对应的对象。

抽象工厂模式

前提概念

  1. 产品等级结构

产品等级结构指的是产品的继承结构,例如一个空调抽象类,它有海尔空调、格力空调、美的空调等一系列的子类,那么这个空调抽象类和他的子类就构成了一个产品等级结构。

  1. 产品族

产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。比如,海尔工厂生产海尔空调、海尔冰箱,那么海尔空调则位于空调产品族中。

  1. 实体图
    在这里插入图片描述

定义

**抽象工厂模式主要用于创建相关对象的家族。**当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象

并且通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

缺点

在于添加新的行为时比较麻烦,如果需要添加一个新产品族对象时,需要更改接口及其下所有子类,这必然会带来很大的麻烦。

具体实现

  1. 产品类
//发动机以及型号  
public interface Engine {}  
 
public class EngineA implements Engine{  
    public EngineA(){  
        System.out.println("制造-->EngineA");  
    }  
}  
public class EngineB implements Engine{  
    public EngineB(){  
        System.out.println("制造-->EngineB");  
    }  
}  
 
 
//空调以及型号  
public interface Aircondition {} 
 
public class AirconditionA implements Aircondition{  
    public AirconditionA(){  
        System.out.println("制造-->AirconditionA");  
    }  
}  
public class AirconditionB implements Aircondition{  
    public AirconditionB(){  
        System.out.println("制造-->AirconditionB");  
    }  
} 
  1. 工厂类
//创建工厂的接口  
public interface AbstractFactory {  
    //制造发动机
    public Engine createEngine();
    //制造空调 
    public Aircondition createAircondition(); 
}  
 
//为宝马320系列生产配件  
public class FactoryBMW320 implements AbstractFactory{ 
    //发动机
    @Override  
    public Engine createEngine() {  
        //在这里新建一个对象
        return new EngineA();  
    }  
    //空调
    @Override  
    public Aircondition createAircondition() { 
        //在这里新建一个对象
        return new AirconditionA();  
    }  
}  
//为宝马523系列胜场配件
public class FactoryBMW523 implements AbstractFactory {
    //发动机
    @Override  
    public Engine createEngine() {   
        //在这里新建一个对象
        return new EngineB();  
    }  
    //空调
    @Override  
    public Aircondition createAircondition() {  
        //在这里新建一个对象
        return new AirconditionB();  
    }  
} 
  1. 客户类
public class Customer {  
    public static void main(String[] args){  
        //生产宝马320系列配件
        //创建具体工厂对象
        FactoryBMW320 factoryBMW320 = new FactoryBMW320();  		//通过具体工厂对象创建同一族产品
        factoryBMW320.createEngine();
        factoryBMW320.createAircondition();
          
        //生产宝马523系列配件  
        FactoryBMW523 factoryBMW523 = new FactoryBMW523();  
        factoryBMW523.createEngine();
        factoryBMW523.createAircondition();
    }  
}
  1. 产品->工厂->客户使用

单例模式

定义

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

俗话说

类似与你的心脏,在你的身体里有且只有一个,无论怎么变化,它都是同一个对象。

特点

  1. 单例类只能有一个实例
  2. 单例类必须自己创建自己的唯一实例
  3. 单例类必须给所有其他对象提供这一实例

作用

单例模式就是为了避免不一致状态,避免政出多头。

分类

  1. 懒汉式(懒得自己动,靠别人调用)

在第一次调用的时候实例化自己

public class Singleton {
    private Singleton() {}
    private static Singleton single=null;
    //静态工厂方法(当第一次调用getInstance() 方法的时候自动创建对象)
    public static Singleton getInstance() {
         if (single == null) {  
             single = new Singleton();
         }  
        return single;
    }
}
  1. 饿汉式(饿得不行了,类刚加载的时候就自己实例化)

在类初始化时,已经自行实例化

public class Singleton1 {
    private Singleton1() {}
    //类初始化的时候就实例化对象,而不是调用方法才实例化
    private static final Singleton1 single = new Singleton1();
    //静态工厂方法 
    public static Singleton1 getInstance() {
        return single;
    }
}
  1. 线程安全的单例模式(进阶版:加了个线程同步)

在懒汉式单例模式基础上加上线程同步

原理

代码对静态方法 getInstance()进行同步,以确保多线程环境下只创建一个实例。如果getInstance()方法未被同步,并且线程A和线程B同时调用此方法,则执行if (instance == null)语句时都为真,那么线程A和线程B都会创建一个对象,在内存中就会出现两个对象,这样就违反了单例模式。而使用synchronized关键字进行同步后,则不会出现此种情况。

public class Singleton {                         
         private static Singleton instance = null;     
         // 私有构造方法,保证外界无法直接实例化。     
         private Singleton() {}                                   
        // 通过公有的静态方法获取对象实例     
        synchronized public static Singleton getInstace() {         
                  if (instance == null) {                                 
                  instance = new Singleton();         }                
                  return instance;     }                                               
}

建造者模式

建造者模式是一种创建型设计模式,也叫生成器模式。

定义

封装一个复杂对象构造过程,并允许按步骤构造。

就是将复杂对象的创建过程拆分成多个简单对象的创建过程,并将这些简单对象组合起来构建出复杂对象。

建造者模式是一种对象创建型模式,它将构建复杂对象的过程和表示进行分离,使得同样的构建过程可以创建不同的表示。

优点

  1. 灵活:可以分步骤地构建复杂对象,使得构建过程更加灵活。
  2. 解耦:可以隔离复杂对象的创建和使用,客户端不必关心对象的创建细节。
  3. 易扩展:增加新的具体建造者很方便,可以扩展构建器功能,符合开闭原则。

缺点

  1. 增加工作量:需要额外的代码来创建和管理具体建造者类,增加了程序员的工作量。

  2. 效率低:相比于其他创建型模式,在运行时效率较低,特别是对象太复杂时。

角色组成

  1. 产品类(Product):表示被创建的复杂对象。它通常包含多个部分或者组成,并由具体的建造者逐步构建而成。
  2. 抽象建造者类(Builder):定义了建造复杂对象所需要的各个部分的创建方法。它通常包括多个构建方法和一个返回产品的方法。
  3. 具体建造者类(ConcreteBuilder):实现Builder接口,并提供各个部分或者组成的构建方法。
  4. 指挥者类(Director):负责控制建造者的构建顺序,指挥建造者如何构建复杂对象。

应用场景

  1. 生活场景
  • 盒饭套餐:顾客可以选择不同的菜,服务员按照顾客的要求,将这些菜组合起来,最终构建出一个完整的套餐。
  • 盖房子:需要分多个阶段进行,比如准备材料、打地基、盖围墙…。建造者模式可以将房屋的建造分解成多个步骤,每个步骤对应一个具体的建造者,最终由包工头(指导者)来调用不同的建造者,完成整个房子的建造。
  1. java场景
  • StringBuilder:能够动态地构建字符串。
  • Stream API:将集合类转为stream流,通过一系列的中间操作和终止操作来生成最终结果。
  • Lombok的@Builder注解:一个注解就可以生成建造者模式的代码。

代码实现

肯德徳都吃过吧,里面有很多的套餐。假设套餐主要由汉堡、薯条和饮料三种组成,每个组件都有不同种类和大小,并且每个套餐的组合方式也不同。下面以肯德徳套餐为例,解释建造者模式。

  1. 产品类:Meal
/**
 * 1.产品类(Product)
 */
@Data
public class Meal {
 
    //汉堡包
    private String burger;
 
    //薯条
    private String fries;
 
    //饮料
    private String drink;
}
  1. 抽象建造者类:MealBuilder
/**
 * 2.抽象建造者(Builder)
 */
public abstract class MealBuilder {
 
    protected Meal meal=new Meal();
 
    //构建汉堡
    public abstract void buildBurger();
 
    //构建薯条
    public abstract void buildFries();
 
    //构建饮料
    public abstract void buildDrink();
 
    public Meal getMeal(){
        return meal;
    }
}c
  1. 具体建造者类:BeefBurgerMealBuilder、ChickenMealBuilder、ShrimpMealBuilder
/**
 * 3.具体建造者(ConcreteBuilder):鸡肉汉堡套餐
 */
public class ChickenMealBuilder extends MealBuilder{
    @Override
    public void buildBurger() {
        meal.setBurger("鸡肉汉堡");
    }
 
    @Override
    public void buildFries() {
        meal.setFries("中份薯条");
    }
 
    @Override
    public void buildDrink() {
        meal.setDrink("大杯果汁");
    }
}

/**
 * 3.具体建造者(ConcreteBuilder):牛肉汉堡套餐
 */
public class BeefBurgerMealBuilder extends MealBuilder {
 
    @Override
    public void buildBurger() {
        meal.setBurger("牛肉汉堡");
    }
 
    @Override
    public void buildFries() {
        meal.setFries("大份薯条");
    }
 
    @Override
    public void buildDrink() {
        meal.setDrink("中杯可乐");
    }
}


/**
 * 3.具体建造者(ConcreteBuilder):虾肉汉堡套餐
 */
public class ShrimpMealBuilder extends MealBuilder {
    @Override
    public void buildBurger() {
        meal.setBurger("虾肉汉堡");
    }
 
    @Override
    public void buildFries() {
        meal.setFries("小份薯条");
    }
 
    @Override
    public void buildDrink() {
        meal.setDrink("大杯芬达");
    }
}
  1. 指挥者类:MealDirector
/**
 * 4.指导者(Director)
 */
public class MealDirector {
    private MealBuilder mealBuilder;
 
    public void setMealBuilder(MealBuilder mealBuilder){
        this.mealBuilder=mealBuilder;
    }
 
    public Meal getMeal(){
        return mealBuilder.getMeal();
    }
 
    //制作套餐
    public void constructMeal(){
        mealBuilder.buildBurger();
        mealBuilder.buildFries();
        mealBuilder.buildDrink();
    }
}
  1. 测试
/**
 * 建造者模式测试类
 */
@SpringBootTest
public class TestBuilder {
 
    @Test
    void testBuilder(){
        //创建指导者
        MealDirector director=new MealDirector();
 
        //执导建造牛肉套餐
        director.setMealBuilder(new BeefBurgerMealBuilder());
        director.constructMeal();
        Meal meal = director.getMeal();
        System.out.println("牛肉套餐:"+meal.toString());
 
        //鸡肉套餐
        director.setMealBuilder(new ChickenMealBuilder());
        director.constructMeal();
        Meal meal2 = director.getMeal();
        System.out.println("鸡肉套餐:"+meal2.toString());
 
        //虾肉套餐
        director.setMealBuilder(new ShrimpMealBuilder());
        director.constructMeal();
        Meal meal3 = director.getMeal();
        System.out.println("虾肉套餐:"+meal3.toString());
    }
}

总结

使用场景:

  1. 当需要创建一些特定的对象,但是它们拥有共同的组成部分时,比如:一个房子可以由个个部件:框架、墙、窗户等,这些部件可以组合起来构造完整的房子。
  2. 当对象的构建过程比较复杂且需要多个步骤时,例如,创建一份电子商务订单需要多个步骤,如选择商品、填写地址和支付等,这些步骤可以被分别封装成为订单构建器中的不同方法。
  3. 当需要创建一些特定类型的对象,例如复杂的数据结构或配置对象时,这在编写配置文件解析器以及通用数据结构如二叉树等时很有用。
  4. 建造者模式也可以被用于通过更高级的方式来构建复杂对象,例如:序列化和反序列化。

与抽象工厂模式的区别:

抽象工厂模式强调的是产品族的创建,即相关的产品一起被创建出来,而建造者模式强调的是一个复杂对象的创建,即它的各个部分逐步被创建出来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1942507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java---后端事务管理

代码世界聚眸光,昼夜敲盘思绪长。 算法心间精构建,编程路上细思量。 屏前架构乾坤定,键上飞驰智慧扬。 默默耕耘成果现,创新科技铸辉煌。 目录 一,概念 二,Spring事务管理 三,rollbackFor事务回…

深入了解软件架构:组件、容器与模块架构图详解

引言 在软件工程中,架构图是描绘系统结构和组件之间关系的重要工具。其中,组件架构图、子系统依赖分析(容器图)和模块架构图是三种常用的架构表示方法,它们各有侧重,适用于不同层面的架构分析与设计。本文…

JMeter请求导出Excel

前言 今天记录一个使用JMeter模拟浏览器请求后端导出,并下载Excel到指定位置的过程 创建请求 同样先创建一个线程组,再创建一个请求,设置好请求路径,端口号等 查看结果树 右键--添加--监听器--查看结果树 这里可以查看&#…

C语言 | Leetcode C语言题解之第273题整数转换英文表示

题目: 题解: char* singles[] {"", "One ","Two ","Three ","Four ","Five ","Six ","Seven ","Eight ","Nine "}; char* teens[] {"Ten…

二十、Qt位置相关函数

目录 一、函数概述 二、函数实践 三、总结 一、函数概述 Qt 提供了很多关于获取窗体位置及显示区域大小的函数,如 x()、y()和 pos()、react()、size()、geometry()等,统称为“位置相关函数”或“位置函数”, 如下图所示是几种主要的位置函数…

MybatisPlusException: Error: Method queryTotal execution error of sql 的报错解决

项目场景: 相关背景: 开发环境 开发系统时 系统页面加载正常 ,发布运行环境后运行一段时间,前端页面 突然出现 报错信息, 报错信息如下: MybatisPlusException: Error: Method queryTotal execution erro…

gitee的怎么上传项目

前提 1.先下载Git Bash (如果没有下载的宝子们下载连接如下: 链接: link ) 项目上传到Gitee步骤 1.在Gitee上建立远程仓库 2.填写相关信息 3.进入本地你想要上传的文件目录下,右键单击空白处,点击Git Bash Here 4.配置你的用户名和邮箱 git con…

【快速逆向二/无过程/有源码】掌上高考—2024高考志愿填报服务平台

逆向日期:2024.07.21 使用工具:Node.js 加密工具:Crypto-js标准库 文章全程已做去敏处理!!! 【需要做的可联系我】 AES解密处理(直接解密即可)(crypto-js.js 标准算法&…

【JVM基础04】——组成-什么是虚拟机栈?

目录 1- 引言:虚拟机栈1-1 虚拟机栈是什么?(What)1-2 为什么用虚拟机栈?虚拟机栈的作用 (Why) 2- ⭐核心:栈的常见问题(How)2-1 方法内的局部变量是否线程安全?线程不安全的局部变量 2-2 什么情况会导致栈内存溢出&…

数据传输工具性能深度评测(阿里云、百度智能云)

阿里云、百度智能云作为领先的云服务提供商,都为数据库提供了配套的数据库工具服务,其中 DTS 是迁移与同步业务的核心服务,本次测试旨在深入比较阿里云与百度智能云在 DTS 数据传输服务性能方面的表现,为企业在选择合适的数据传输…

电商比价平台的功能讲解及数据采集分析

引言 随着电子商务的快速发展,电商比价平台作为连接消费者与供应商的重要桥梁,其重要性日益凸显。这类平台通过自动化的比价功能,不仅帮助消费者快速找到性价比最高的商品,还为企业提供了高效的采购工具,实现了采购成…

winfrom 文件自动生成

数据页面展示 添加定时器执行每个表数据的生成计划 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.IO; using System.Windows.Forms; using …

qt中charts图表的使用方法

折线图 #include "widget.h" #include "ui_widget.h" #include <QtCharts/QChart> #include <QtCharts/QChartView> #include <QtCharts/QLineSeries> #include<QVBoxLayout>Widget::Widget(QWidget *parent): QWidget(parent), …

知识图谱 | 基于电商网站中的商品分类目录构建知识图谱

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目旨在构建一个基于电商网站商品分类目录的知识图谱&#xff0c;通过Python程序爬取分类信息&#xff0c;形成商品的目录树&#xff0c;并提取底层商品的概念信息。项目将重点展示如何利用知识图谱呈现概念层级知识&#xf…

等保测评练习卷17

等级保护初级测评师试题17 姓名&#xff1a; 成绩&#xff1a; 判断题&#xff08;10110分&#xff09; 1. 关于安全区域边界的安全审计&#xff0c;三级系统的要求包括应对审计进程进行保护&#x…

Java实现分卷压缩功能,不引入第三方依赖的实现方式

分卷压缩 分卷压缩是一种将一个大文件分割成多个较小文件的压缩方法。这种方法通常用于便于存储、传输或备份大文件。分卷压缩的主要特点和步骤包括: 分割大文件:将一个大文件分割成多个较小的文件,每个小文件称为一个“分卷”。压缩分卷:对每个分卷进行压缩,以减少每个分…

【复习】软件工程

软件危机是指在计算机软件的开发和维护过程中所遇到的一系列严重问题。 典型表现&#xff1a; 开发成本和进度的估计常常很不准确 用户对已完成的软件系统不满意&#xff0c;闭门造车 软件质量&#xff08;quality&#xff09;不可靠 软件常常是不可维护的 软件产品供不应…

java的DOS命令

目录 1.DOS命令了解 DOS介绍 常用的dos命令1 DOS的基本原理 相对路径与绝对路径 常用的dos命令2 2.本章作业 1.编写hello&#xff0c;world程序 2.输出个人基本信息 3.jdk&#xff0c;jre&#xff0c;jvm关系 4.环境变量path配置及作用 5.java编写步骤 6.java编写7…

14、如何⽤DDD设计微服务代码模型

在完成领域模型设计后&#xff0c;接下来我们就可以开始微服务的设计和 落地了。在微服务落地前&#xff0c;⾸先要确定微服务的代码结构&#xff0c;也就是我 下⾯要讲的微服务代码模型。 只有建⽴了标准的微服务代码模型和代码规范后&#xff0c;我们才可以将 领域对象映射到…

C#初级——输出语句和转义字符

输出语句 在C#中&#xff0c;C#的输出语句是通过Console类进行输出&#xff0c;该类是一个在控制台下的一个标准输入流、输出流和错误流。使用该类下的Write()函数&#xff0c;即可打印要输出的内容。 Console.Write("Hello World!"); //在控制台应用中打印Hell…