Gof23-创建型-工厂-单例-抽象工厂-建造-原型以及UML的绘制

news/2024/5/4 15:22:22/文章来源:https://blog.csdn.net/qq_46724069/article/details/128026461

创建型的设计模式

  • 工厂模式
  • 单例模式
  • 抽象工厂
  • 建造者模式
  • 原型模式
  • UML图形的绘制

工厂模式

工厂模式 Factory Pattern

适用的场景:统一的接口作为统一的零件,实现类作为零件的组合,将实例产品类的生产交给工厂,用户只需要面对工程提取指定的产品。

比如:客户需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现

思想创建的过程在子类中实现

具体实现,创建一个接口,创建多个接口的实现类,重写实现对应的方法,创建一个工厂类,工厂类中实现方法传入类型生产对应的接口实现类,返回接口,编写测试方法,new一个工厂传入多个类型就可以生产对应的产品了。

在这里插入图片描述

class CarFactory{public Production getProduction(String type){if (type == null) return null;if (type.equalsIgnoreCase("BaoMa")){return new BaoMa();} else if (type.equalsIgnoreCase("BiYaDi")) {return new BiYaDi();} else if (type.equalsIgnoreCase("AoDi")) {return new AoDi();}return null;}
}class BaoMa implements Production{@Overridepublic void production() {System.out.println("宝马车工厂生产中......");}
}class BiYaDi implements Production{@Overridepublic void production() {System.out.println("比亚迪车工厂生产中......");}
}class AoDi implements Production{@Overridepublic void production() {System.out.println("奥迪车工厂生产中......");}
}interface Production{void production();
}

测试方法

    public static void main(String[] args) {CarFactory carFactory = new CarFactory();carFactory.getProduction("baoma").production();carFactory.getProduction("aodi").production();carFactory.getProduction("biyadi").production();}

单例模式

单例模式 Singleton Pattern

适用的场景,保证一个类仅有一个实例,并提供一个访问它的全局访问点。

例如,一个班级只有一个班主任,window对同一个文件的处理,设备处理器,打印机

具体实现,一个类有且具有一个实例,并且构造器私有,分为饿汉式单例和懒汉式单例

在这里插入图片描述

饿汉式单例

在类初始化的时就实例化对象,因此它是线程安全的,存在的问题就是使用不当,会造成空间资源的浪费

class Hungry{private final static Hungry hungry = new Hungry();private Hungry() {}public static Hungry getHungry() {return hungry;}public void hello(){System.out.println("饿汉式单例的hello()");}
}

存在问题,如果在Hungry的代码中加入一下代码,那么在类初始化时候,占用了这些空间,但是没有使用,就造成空间资源的浪费。

    byte[] a = new byte[1024*1024];byte[] b = new byte[1024*1024];byte[] c = new byte[1024*1024];

测试方法,仅能通过类在最开始私有进行实例化对象进行操作方法

    public static void main(String[] args) {// 仅仅能通过私有构造器进行对象的初始化工作,并且在最开始就进行了对象的初始化Hungry hungry = Hungry.getHungry();hungry.hello();}

懒汉式单例

不安全的基本的懒汉式单例,在get实例方法时候加入判空操作

class LazyMan{private static LazyMan lazyMan;private LazyMan() {}public static LazyMan getLazyMan() {if (lazyMan == null){lazyMan = new LazyMan();}return lazyMan;}public void hello(){System.out.println("饿汉式单例的hello()");}
}

测试方法

    public static void main(String[] args) {LazyMan lazyMan = LazyMan.getLazyMan();lazyMan.hello();}

存在问题懒汉单例,当程序启动之后并不会进行初始化,在什么时候调用什么时候初始化。单线程下没有问题,但是在多线程下,由于没有加锁,所以会存在访问问题。

思考什么情况会导致线程不安全

  • 线程的调度是抢占式执行
  • 修改操作不是原子的
  • 多个线程同时修改同一个变量
  • 内存可见性
  • 指令重排序

在并发访问的时候,线程实并发来访问这个懒汉式单例的,多个线程访问的结果不一致

加锁保证懒汉式单例的安全,直接在方法上进行加锁,但是锁的粒度过大,相对比较笨重

    public static synchronized LazyMan getLazyMan() {if (lazyMan == null){lazyMan = new LazyMan();}return lazyMan;}

DCL优化加锁,在方法上双重检查锁,加入voliate关键字,作用是内存可见性,禁止指令重排序

class LazyMan{private volatile static LazyMan lazyMan;private LazyMan() {}public static LazyMan getLazyMan() {if (lazyMan == null){synchronized (LazyMan.class){if (lazyMan == null){lazyMan = new LazyMan();}}}return lazyMan;}public void hello(){System.out.println("饿汉式单例的hello()");}
}

抽象工厂

抽象工厂 abstract Factory

使用场景,一个超级工厂去创建其他的小工厂,主要解决接口选择的问题。

例如,QQ 换皮肤,一整套一起换。 生成不同操作系统的程序。

在这里插入图片描述

具体实现

定义具体实现的两个接口,包含了各自的方法

interface Shape{public void draw();
}interface Color{public void fill();
}

接口实现类,具体实现接口方法

class Rectangle implements Shape{@Overridepublic void draw() {System.out.println("画出一个长方形");}
}class Trangle implements Shape{@Overridepublic void draw() {System.out.println("画出一个三角形");}
}class Circle implements Shape{@Overridepublic void draw() {System.out.println("画出一个圆形");}
}class Red implements Color{@Overridepublic void fill() {System.out.println("该图形填充了Red");}
}class Blue implements Color{@Overridepublic void fill() {System.out.println("该图形填充了Blue");}
}class Green implements Color{@Overridepublic void fill() {System.out.println("该图形填充了Green");}
}

定义抽象工厂类,每一个具体的工厂类继承这个抽象工厂类,在这个具体的工厂类中实现对应的零件

abstract class AbstractFactory{public abstract Shape getShape(String shape);public abstract Color getColor(String color);
}class ShapeFactory extends AbstractFactory{@Overridepublic Shape getShape(String shape) {if (shape == null) return null;if (shape.equalsIgnoreCase("Rectangle")){return new Rectangle();} else if (shape.equalsIgnoreCase("Trangle")) {return new Trangle();} else if (shape.equalsIgnoreCase("Circle")) {return new Circle();}return null;}@Overridepublic Color getColor(String color) {return null;}
}class ColorFactory extends AbstractFactory{@Overridepublic Shape getShape(String shape) {return null;}@Overridepublic Color getColor(String color) {if (color == null) return null;if (color.equalsIgnoreCase("Red")){return new Red();} else if (color.equalsIgnoreCase("Blue")) {return new Blue();} else if (color.equalsIgnoreCase("Green")) {return new Green();}return null;}
}

由于这个抽象工厂没有实例,所以需要一个工厂处理器,来处理抽象工厂,让其返回用户需要

class FactoryProducer{public AbstractFactory getFactory(String factory){if (factory == null) return null;if (factory.equalsIgnoreCase("ShapeFactory")){return new ShapeFactory();} else if (factory.equalsIgnoreCase("ColorFactory")) {return new ColorFactory();}return null;}
}

测试方法,工厂处理器通过抽象的超级工厂获取工厂的类型,通过指定的工厂就可以对指定的工具类进行操作

    public static void main(String[] args) {FactoryProducer factoryProducer = new FactoryProducer();AbstractFactory shapeFactory = factoryProducer.getFactory("ShapeFactory");shapeFactory.getShape("Rectangle").draw();shapeFactory.getShape("Trangle").draw();shapeFactory.getShape("Circle").draw();AbstractFactory colorFactory = factoryProducer.getFactory("ColorFactory");colorFactory.getColor("Red").fill();colorFactory.getColor("Blue").fill();colorFactory.getColor("Green").fill();}

建造者模式

建造者模式 Builder Pattern

使用多个简单的对象一步一步构建成一个复杂的对象,建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。

应用,去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。JAVA 中的 StringBuilder。

厂模式的区别是:建造者模式更加关注与零件装配的顺序。

在这里插入图片描述

具体实现

创建接口,套餐项的接口,包装接口

// 套餐项,喝的,吃的
interface Item{public String name();public Packing packing();public float price();
}
// 包装:纸质包装,瓶装
interface Packing{public String pack();
}

包装接口的实现类,纸质包装和瓶装

class Wrapper implements Packing {@Overridepublic String pack() {return "Wrapper";}
}class Bottle implements Packing {@Overridepublic String pack() {return "Bottle";}
}

抽象类封装基本的套餐项,饮料采用瓶子装,汉堡采用纸质装

// 创建实现 Item 接口的抽象类,该类提供了默认的功能。基本的汉堡,饮料的种类
abstract class ColdDrink implements Item {@Overridepublic Packing packing() {return new Bottle();}@Overridepublic abstract float price();
}abstract class Burger implements Item {@Overridepublic Packing packing() {return new Wrapper();}@Overridepublic abstract float price();
}

创建扩展了 Burger ColdDrink 的实体类。在汉堡上再封装成为蔬菜汉堡,鸡肉汉堡等,在喝的项目上封装可乐等饮料


class VegBurger extends Burger {@Overridepublic float price() {return 25.0f;}@Overridepublic String name() {return "Veg Burger";}
}
class ChickenBurger extends Burger {@Overridepublic float price() {return 50.5f;}@Overridepublic String name() {return "Chicken Burger";}
}class Coke extends ColdDrink {@Overridepublic float price() {return 30.0f;}@Overridepublic String name() {return "Coke";}
}
class Pepsi extends ColdDrink {@Overridepublic float price() {return 35.0f;}@Overridepublic String name() {return "Pepsi";}
}

item存入集合,并且计算套餐的价值及其一系列附加属性

class Meal {private List<Item> items = new ArrayList<Item>();public void addItem(Item item){items.add(item);}public float getCost(){float cost = 0.0f;for (Item item : items) {cost += item.price();}return cost;}public void showItems(){for (Item item : items) {System.out.print("Item : "+item.name());System.out.print(", Packing : "+item.packing().pack());System.out.println(", Price : "+item.price());}}
}

Builder类,负责准备两种不同的套餐,有蔬菜的套餐和没有蔬菜的套餐

class MealBuilder {public Meal prepareVegMeal (){Meal meal = new Meal();meal.addItem(new VegBurger());meal.addItem(new Coke());return meal;}public Meal prepareNonVegMeal (){Meal meal = new Meal();meal.addItem(new ChickenBurger());meal.addItem(new Pepsi());return meal;}
}

测试方法

    public static void main(String[] args) {MealBuilder mealBuilder = new MealBuilder();Meal vegMeal = mealBuilder.prepareVegMeal();System.out.println("Veg Meal");vegMeal.showItems();System.out.println("Total Cost: " +vegMeal.getCost());Meal nonVegMeal = mealBuilder.prepareNonVegMeal();System.out.println("\n\nNon-Veg Meal");nonVegMeal.showItems();System.out.println("Total Cost: " +nonVegMeal.getCost());}

原型模式

利用已有的一个原型对象,快速地生成和原型对象一样的实例。通常用于克隆,可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。

优点 性能提高。 逃避构造函数的约束。

应用 细胞分裂。JAVA 中的 Object clone() 方法。

在这里插入图片描述

具体实现

定义一个含有抽象方法的抽象类,实现克隆的接口

abstract class Shape implements Cloneable {private String id;protected String type;abstract void draw();public String getType(){return type;}public String getId() {return id;}public void setId(String id) {this.id = id;}public Object clone() {Object clone = null;try {clone = super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return clone;}
}

给抽象类进行扩展

class Rectangle extends Shape {public Rectangle(){type = "Rectangle";}@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}class Square extends Shape {public Square(){type = "Square";}@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}class Circle extends Shape {public Circle(){type = "Circle";}@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}

Shape 的缓存类,负责先一步加载缓存

class ShapeCache {private static Hashtable<String, Shape> shapeMap= new Hashtable<String, Shape>();public static Shape getShape(String shapeId) {Shape cachedShape = shapeMap.get(shapeId);return (Shape) cachedShape.clone();}public static void loadCache() {Circle circle = new Circle();circle.setId("1");shapeMap.put(circle.getId(),circle);Square square = new Square();square.setId("2");shapeMap.put(square.getId(),square);Rectangle rectangle = new Rectangle();rectangle.setId("3");shapeMap.put(rectangle.getId(),rectangle);}
}

测试方法

public static void main(String[] args) {ShapeCache.loadCache();Shape clonedShape = (Shape) ShapeCache.getShape("1");System.out.println("Shape : " + clonedShape.getType());        Shape clonedShape2 = (Shape) ShapeCache.getShape("2");System.out.println("Shape : " + clonedShape2.getType());        Shape clonedShape3 = (Shape) ShapeCache.getShape("3");System.out.println("Shape : " + clonedShape3.getType());        }

UML图形的绘制

interface class之间的关系与对象与对象之间的关系

泛化关系也就是继承关系

在这里插入图片描述
-表示 private

+ 表示 public

#表示protected

不带符号代表 default

UML表示具体类
在这里插入图片描述

UML 表示抽象类,抽象类的类名以及抽象方法的名字都用斜体字表示

在这里插入图片描述

接口

在这里插入图片描述
或者(棒棒糖表示法)
在这里插入图片描述

UML 表示包

在这里插入图片描述

实现关系implements,一个类实现了一个接口

在这里插入图片描述

泛化关系extends,也就是类之间的继承关系

is a 关系表示

在这里插入图片描述

关联关系 Association

代码表现形式为一个对象含有另一个对象的引用

关联关系有单向关联和双向关联。如果两个对象都知道(即可以调用)对方的公共属性和操作,那么二者就是双向关联。如果只有一个对象知道(即可以调用)另一个对象的公共属性和操作,那么就是单向关联。大多数关联都是单向关联,单向关联关系更容易建立和维护,有助于寻找可重用的类。

在这里插入图片描述

关联关系又分为依赖关联、聚合关联和组合关联三种类型

依赖关系 Dependency

属于一种弱关联关系,使用 use a

依赖关系在Java中的具体代码表现形式为B为A的构造器或方法中的局部变量、方法或构造器的参数、方法的返回值,或者A调用B的静态方法。

在这里插入图片描述
聚合关系 Aggregation

体现的是整体与部分的拥有关系使用 has a,是一种弱引用关系

此时整体与部分之间是可分离的,它们可以具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享,所以聚合关系也常称为共享关系。

例如,公司部门与员工的关系,一个员工可以属于多个部门,一个部门撤消了,员工可以转到其它部门。

在这里插入图片描述

组合关系 Composition也是关联关系的一种特例,它同样体现整体与部分间的包含关系,即 “contains a” 的关系。强关联关系

例如,人包含头、躯干、四肢,它们的生命周期一致。当人出生时,头、躯干、四肢同时诞生。当人死亡时,作为人体组成部分的头、躯干、四肢同时死亡。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java_接口

目录 1.接口的语法规则 2.接口使用 3.接口特性 4.实现多个接口 1&#xff09;下面通过类来表示一组动物&#xff1b; 2&#xff09;另外再提供一组接口, 分别表示 "会跑的", "会飞的", "会游泳的"&#xff1b; 3&#xff09;接下来我们创建…

十九种卷积

参考文章:一文看尽深度学习中的20种卷积(附源码整理和论文解读) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/381839221 一、原始卷积(Vanilla Convolution) CNNs中的卷积,也称为滤波器,是由一组具有固定窗口大小且带可学习参数(learnable paramerters)的卷积核所组…

Unity 如何实现框选游戏战斗单位

文章目录&#x1f354; Preface✨ 如何在屏幕坐标系内绘制框选框&#x1f389; 根据框选范围定位其在世界坐标系中对应的区域&#x1f947; 在该区域内进行物理检测&#x1f354; Preface 本文简单介绍如何实现即时战略游戏中框选战斗单位的功能&#xff0c;如图所示&#xff…

【外卖项目实战开发二】

文章目录1、完善登录功能问题分析代码实现2、新增员工需求分析数据模型代码开发3、员工信息分页查询需求分析代码开发4、启用/禁用员工账号需求分析代码开发代码修复5、编辑员工信息需求分析代码开发1、完善登录功能 问题分析 前面我们已经完成了后台系统的员工登录功能开发&…

基于JavaWeb的婚恋交友网站设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

大数据:HDFS的Shell常用命令操作

文章目录一 HDFS的Shell介绍二 HDFS常用命令操作01 创建目录&#xff08;1&#xff09;创建单层目录&#xff08;3&#xff09;创建多层目录02 查看目录03 上传本地文件到HDFS04 查看文件内容05 下载HDFS文件到本地06 删除HDFS文件07 删除HDFS目录08 移动目录或文件09 文件合并…

第九章 堆排序与TOPK问题

第九章&#xff1a;堆排序与TOPK问题一、堆排序&#xff1a;1、思路分析&#xff1a;&#xff08;1&#xff09;建堆&#xff08;2&#xff09;排序2、堆排序模板二、TOPK问题&#xff1a;1、什么是TOPK问题&#xff1f;2、解决方法一、堆排序&#xff1a; 假设我们实现一个小…

26k Star, 理解Git太轻松了。。。

程序员宝藏库&#xff1a;gitee.com/sharetech_lee/CS-Books-Store Git是目前使用比较广泛一款版本控制工具&#xff0c;从事开发工作&#xff0c;很难绕开Git。 因此&#xff0c;关于如何快速学习Git使用一直都是一个经久不衰的话题。 前不久我在另外一篇文章中曾提到Git对初…

树莓派上搭建SVN服务器

目录 一、服务端安装步骤 1.安装svn 2.创建目录 3.创建版本仓库 4.修改配置&#xff08;authz,passwd,svnserve.conf&#xff09; 5.启动服务 二、tortoisSVN客户端安装 三、结束 一、服务端安装步骤 1.安装svn sudo apt-get install subversion 2.创建目录 sudo m…

用Python蹭别人家图片接口,做一个【免费图床】吧

打开本文&#xff0c;相信你确实需要一个免费且稳定的图床&#xff0c;这篇博客就让你实现。 文章目录⛳️ 谁家的图床⛳️ 实战编码⛳️ 第一轮编码⛳️ 第二轮编码⛳️ 第三轮编码⛳️ 第四轮编码⛳️ 谁家的图床 这次咱们用新浪微博来实现【免费图床应用】&#xff0c;通过…

基于keras 卷积神经外网络搭建的手写数字识别 完整代码+数据可直接运行

项目介绍: 适合新手入门学习代码数据很简洁 上结果: 主要的卷积神经网络: 卷积是指在滑动中提取特征的过程,可以形象地理解为用放大镜把每步都放大并且拍下来,再把拍下来的图片拼接成一个新的大图片的过程。 2D卷积是一个相当简单的操作: 我们先从一个小小的权重矩阵…

十个值得珍藏的正则表达式

正则表达式常学常忘&#xff0c;记规则不如记例子&#xff0c;记多不如记精&#xff0c;记例子就记最经典的。下面是本人珍藏的十个有用的正则表达式&#xff0c;不吝分享&#xff0c;以飨读者。 正则表达式要点 小括号&#xff1a;代表分组 中括号&#xff1a;代表集合 大括号…

外卖项目08---Linux

目录 一、 Linux简介 119 二、Linux安装 120 三、常用命令 122 3.1Linux命令初体验 3.1.1 command [-options] [parameter] 3.2Linux常用命令---文件目录操作命令-ls&-cd&-cat 124 3.2.1list 3.2.2 cd 3.2.3 cat 3.3 Linux常用命令---文件目录操作命令…

机器学习模型与backtrader框架整合

原创文章第116篇&#xff0c;专注“个人成长与财富自由、世界运作的逻辑&#xff0c; AI量化投资”。 北京疫情似乎还没有到拐点&#xff0c;但这三天结束后应该会到来。 今天重点说说&#xff0c;机器学习模型整合到我们的回测框架中&#xff0c;并与backtrader连接起来回测…

傻白入门芯片设计,先进封装技术(五)

集成电路芯片与封装之间是不可分割的整体。没有一个芯片可以不用封装就能正常工作&#xff0c;封装对芯片来说是必不可少的&#xff0c;随着IC生产技术的进步&#xff0c;封装技术也不断更新换代&#xff0c;每一代IC都与新一代的IC封装技术紧密相连。 目录 一、什么是封装&am…

详解设计模式:抽象工厂模式

工厂方法模式&#xff0c;又称工厂模式、多态工厂模式和虚拟构造器模式&#xff0c;通过工厂父类定义负责创建产品的公共接口&#xff0c;子类负责生产具体对象。可以理解为简单工程模式的升级&#xff0c;解决简单工厂模式的弊端。 &#xff5e; 本篇内容包括&#xff1a;关于…

java基本语法 下

目录 运算符 运算符&#xff1a;算术运算符 运算符&#xff1a;赋值运算符 运算符&#xff1a;比较运算符 运算符&#xff1a;逻辑运算符 运算符&#xff1a;三元运算符 运算符的优先级 程序流程控制 概念 顺序结构 if-else结构 switch-case结构 循环结构 循环结构…

你不能错过的【Python爬虫】测试3(爬取所有内容 + 完整源代码 + 架构 + 结果)

目录 一、主要工具包 以及 版本二、架构展示三、各部分code3.1 yjs.py (重要)3.2 items.py3.3 middlewares.py3.4 pipelines.py3.5 settings.py3.6 start.py四、结果展示一、主要工具包 以及 版本 scrapy:2.7.1版本(这里主要用到的工具包) 二、架构展示 三、各部分code 3…

8、MyBatis核心配置文件之typeAliases(mybatis-config.xml)

MyBatis核心配置文件之typeAliases&#xff08;mybatis-config.xml&#xff09; 1、&#xff01;&#xff01;&#xff01;&#xff01;注意 2、 设置类型别名&#xff08;比如有的全类名&#xff08;resultType&#xff09;太长了不好使用&#xff09; typeAlias :设置某个类…

AOP实现方式-P20,21,22

项目的包&#xff1a; pom依赖导入有关aop的包&#xff1a; <dependencies><!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactI…