设计模式——创建型设计模式
创建型设计模式
争对
对象/类
创建时的优化
工厂方法模式(了解)
通过定义顶层抽象工厂类,通过继承的方式,针对于每一个产品都提供一个工厂类用于创建。
情况:只适用于简单对象,当我们需要生产许多个产品族的时候,这种模式就有点乏力了
创建对象不再使用传统的new,而是创建一个工厂类,作为all实体类创建对象的一个封装类。(避免了更改类名、构造方法时,需要修改大量的代码)
简单工厂模式:(不灵活,不建议)
不符合开闭原则。如果输入没有提前写好的水果则就需要再添加每个类里的代码
//水果抽象类
public abstract class Fruit { private final String name;public Fruit(String name){this.name = name;}@Overridepublic String toString() {return name+"@"+hashCode(); //打印一下当前水果名称,还有对象的hashCode}
}//水果实体类
public class Apple extends Fruit{ //苹果,继承自水果public Apple() {super("苹果");}
}
public class Orange extends Fruit{ //橘子,也是继承自水果public Orange() {super("橘子");}
}//水果工厂
public class FruitFactory {/*** 这里就直接来一个静态方法根据指定类型进行创建* @param type 水果类型* @return 对应的水果对象*/public static Fruit getFruit(String type) {switch (type) {case "苹果":return new Apple();case "橘子":return new Orange();default:return null;}}
}//主方法
public class Main {public static void main(String[] args) {Fruit fruit = FruitFactory.getFruit("橘子"); //直接问工厂要,而不是我们自己去创建System.out.println(fruit);}
}
工厂方法模式:通过范型灵活实现
如果新增了水果类型,直接创建一个新的工厂类就行,不需要修改之前已经编写好的内容。
缺点:一种水果就有一种新的工厂类,太多工厂类了
//水果抽象类
public abstract class Fruit { private final String name;public Fruit(String name){this.name = name;}@Overridepublic String toString() {return name+"@"+hashCode(); //打印一下当前水果名称,还有对象的hashCode}
}//水果工厂
public abstract class FruitFactory<T extends Fruit> { //将水果工厂抽象为抽象类,添加泛型T由子类指定水果类型public abstract T getFruit(); //不同的水果工厂,通过此方法生产不同的水果
}//Apple工厂
public class AppleFactory extends FruitFactory<Apple> { //苹果工厂,直接返回Apple,一步到位@Overridepublic Apple getFruit() {return new Apple();}
}//主方法
public class Main {public static void main(String[] args) {test(new AppleFactory()::getFruit); //比如我们现在要吃一个苹果,那么就直接通过苹果工厂来获取苹果}//此方法模拟吃掉一个水果private static void test(Supplier<Fruit> supplier){System.out.println(supplier.get()+" 被吃掉了,真好吃。");}
}
抽象工厂模式
情况:适用于有一系列产品的公司。
缺点:容易违背开闭原则。一旦增加了一种产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变
举例:
实际上这些产品都是成族出现的,比如小米的产品线上有小米12,小米平板等,华为的产品线上也有华为手机、华为平板,但是如果按照我们之前工厂方法模式来进行设计,那就需要单独设计9个工厂来生产上面这些产品,显然这样就比较浪费时间的。
我们就可以使用抽象工厂模式,我们可以将多个产品,都放在一个工厂中进行生成,按不同的产品族进行划分,比如小米,那么我就可以安排一个小米工厂,而这个工厂里面就可以生产整条产品线上的内容,包括小米手机、小米平板、小米路由等。
//工厂抽象类
public abstract class AbstractFactory {public abstract Phone getPhone();public abstract Table getTable();public abstract Router getRouter();
}//工厂实现类
public class AbstractFactoryImpl extends AbstractFactory{@Overridepublic Phone getPhone() {return new ProductPhone();}@Overridepublic Table getTable() {return new ProductTable();}@Overridepublic Router getRouter() {return new ProductRouter();}
}//产品抽象类
public abstract class AbRouter{public abstract Router getRouter();
}
...//产品实体类
public class Router extends AbRouter{@Overridepublic Router getRouter(){return new Router();}
}
建造者模式
当构造对象时参数较多,可以通过建造者模式使用链式方法创建对象,保证参数填写正确。
可以去看看StringBuilder的源码,有很多的框架都为我们提供了形如XXXBuilder
的类型,我们一般也是使用这些类来创建我们需要的对象。
建造者模式创建对象其实和StringBuilder
一样:实际上我们是通过建造者来不断配置参数或是内容,当我们配置完所有内容后,最后再进行对象的构建。
public static void main(String[] args) {StringBuilder builder = new StringBuilder(); //创建一个StringBuilder来逐步构建一个字符串builder.append(666); //拼接一个数字builder.append("老铁"); //拼接一个字符串builder.insert(2, '?'); //在第三个位置插入一个字符System.out.println(builder.toString()); //差不多成形了,最后转换为字符串
}
举例:
//实体类的编写
public class Student {int id;int age;int grade;String name;String college;String profession;List<String> awards;//一律使用建造者来创建,不对外直接开放private Student(int id, int age, int grade, String name, String college, String profession, List<String> awards) {this.id = id;this.age = age;this.grade = grade;this.name = name;this.college = college;this.profession = profession;this.awards = awards;}public static StudentBuilder builder(){ //通过builder方法直接获取建造者return new StudentBuilder();}public static class StudentBuilder{ //这里就直接创建一个内部类//Builder也需要将所有的参数都进行暂时保存,所以Student怎么定义的这里就怎么定义int id;int age;int grade;String name;String college;String profession;List<String> awards;public StudentBuilder id(int id){ //直接调用建造者对应的方法,为对应的属性赋值this.id = id;return this; //为了支持链式调用,这里直接返回建造者本身,下同}public StudentBuilder age(int age){this.age = age;return this;}...public StudentBuilder awards(String... awards){this.awards = Arrays.asList(awards);return this;}public Student build(){ //最后我们只需要调用建造者提供的build方法即可根据我们的配置返回一个对象return new Student(id, age, grade, name, college, profession, awards);}}
}
//主方法
public static void main(String[] args) {Student student = Student.builder() //获取建造者.id(1) //逐步配置各个参数.age(18).grade(3).name("小明").awards("ICPC-ACM 区域赛 金牌", "LPL 2022春季赛 冠军").build(); //最后直接建造我们想要的对象
}
单例模式
单例模式:在计算机进程中,同一个类始终只会有一个对象来进行操作。
多例模式:在计算机进程中,对一个实体类创建一次对象就是对当个对象操作,若是创建多个对象则是分别对对应的对象操作。
单例模式的三种写法:
饿汉式单例(不建议)
在最开始就创建了对象(太饥渴了,一开始就需要对象)
public class Singleton {private final static Singleton INSTANCE = new Singleton(); //用于引用全局唯一的单例对象,在一开始就创建好private Singleton() {} //禁用了构造方法Singleton()来创建对象。不允许随便new,需要对象直接找getInstancepublic static Singleton getInstance(){ //获取全局唯一的单例对象return INSTANCE;} }
加锁的懒汉式单例(不建议,没有第三种方法好)
懒汉:在要用的时候才创建对象。但又得防多线程就上了锁
public class Singleton {private static volatile Singleton INSTANCE; //在一开始先不进行对象创建。volatile关键字是多线程的时候,这个变量更改了,别的线程可以立马检测到private Singleton() {} //禁用了构造方法Singleton()来创建对象。不允许随便new,需要对象直接找getInstancepublic static Singleton getInstance(){if(INSTANCE == null) { //这层判断是便于第一次外访问时不用在走锁synchronized (Singleton.class) { //加锁是为了防止多线程创建了多个对象if(INSTANCE == null) INSTANCE = new Singleton(); //由于加了锁,所以当一个进程进来创建了对象,其他线程需要再判断一次有没有人已经创建了这个类对象,有就不创建了。内层还要进行一次检查,双重检查锁定}}return INSTANCE; } }
静态内部类的半懒、半饿式单例(建议)
静态内部类该开始不会加载,需要的时候才会加载,由于这个类一加载就会创建对象。
所以实现了懒汉的资源不滥用,饿汉的防止多线程
public class Singleton {private Singleton() {}//禁用了构造方法Singleton()来创建对象。不允许随便new,需要对象直接找getInstanceprivate static class Holder { //由静态内部类持有单例对象,但是根据类加载特性,我们仅使用Singleton类时,不会对静态内部类进行初始化。一旦类初始化之后值将不会改变,有点饿汉式的味道。private final static Singleton INSTANCE = new Singleton();}public static Singleton getInstance(){ //只有真正使用内部类时,才会进行类初始化return Holder.INSTANCE; //直接获取内部类中的} }
原型模式
定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。(说白了就是复制)
- 浅拷贝:①对于类中基本数据类型,会直接复制值给拷贝对象;②对于引用类型(对象类型),只会复制对象的地址,而实际上指向的还是原来的那个对象,拷贝个基莫。
public static void main(String[] args) {int a = 10;int b = a; //基本类型浅拷贝System.out.println(a == b); //trueObject o = new Object();Object k = o; //引用类型浅拷贝,拷贝的仅仅是对上面对象的引用System.out.println(o == k); //true
}
- 深拷贝:无论是基本类型还是引用类型,深拷贝会将引用类型的所有内容,全部拷贝为一个新的对象,包括对象内部的所有成员变量,也会进行拷贝。
使用Cloneable接口提供的拷贝机制,来实现原型模式:操作完会发现Object的clone
默认还是浅复制
protected class Student implements Cloneable{ //注意需要实现Cloneable接口...//Cloneable中的方法,下面代码复制Object的clone源码 @Overridepublic Object clone() throws CloneNotSupportedException { //提升clone方法的访问权限return super.clone();}
}//主方法
public static void main(String[] args) throws CloneNotSupportedException {Student student0 = new Student();Student student1 = (Student) student0.clone();System.out.println(student0);System.out.println(student1);//两个结果不同,就是地址不同Student student0 = new Student("小明");Student student1 = (Student) student0.clone();System.out.println(student0.getName() == student1.getName());//true
}
深拷贝:在student实现接口Cloneable后重写clone方法
@Override
public Object clone() throws CloneNotSupportedException { //这里我们改进一下,针对成员变量也进行拷贝Student student = (Student) super.clone();student.name = new String(name);return student; //成员拷贝完成后,再返回
}
设计模式——创建型设计模式相关推荐
- 设计模式----创建型设计模式(单例模式、工厂方法模式、构建者模式)
创建型设计模式 单例模式(Singleton Pattern) 单例模式介绍 代码演示 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(线程安全,同步方法) 懒汉式(线程安全, ...
- 设计模式--创建型设计模式
一. 设计模式的目的 编写软件过程中,可能面临来自耦合性.内聚性.可维护性.可扩展性.重用性.灵活性等多方面的挑战,设计模式是为了让程序具有更好的: 代码重用性(即相同的代码,不用多次编写) 可读 ...
- javaScript设计模式-创建型设计模式
我们大家一听到设计模式就感觉设计模式是一个高端的东西,到底什么是设计模式呢?其实设计模式也就是我们的前辈在写代码的时候遇到的问题,提出的解决方案,为了方便人与人之间的交流,取了个名字,叫做设计模式. ...
- 设计模式 - 创建型设计模式小结
分享一个大牛的人工智能教程.零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net 创建型模式比较简单,但是会比较没有意思,结构型和行为 ...
- 创建型设计模式(待更新)
前言 - 熟能生巧(★★★) 关于设计模式的学习,需要结合具体的应用场景进行理解,即站在用户的角度去理解需求,目的是让自己设计的代码能够为用户提供统一的接口,并且设计的模块具有高内聚低耦合.有更好的可 ...
- JAVA设计模式第二讲:创建型设计模式
设计模式(design pattern)是对软件设计中普遍存在的各种问题,所提出的解决方案.本文以面试题作为切入点,介绍了设计模式的常见问题.我们需要掌握各种设计模式的原理.实现.设计意图和应用场景, ...
- 技术图文:02 创建型设计模式(下)
创建型设计模式(下) 知识结构: 图1 知识结构 单例模式 – 确保对象的唯一性 Sunny 软件公司承接了一个服务器负载均衡软件的开发工作,该软件运行在一台负载均衡服务器上,可以将并发访问和数据流量 ...
- 技术图文:02 创建型设计模式(上)
创建型设计模式(上) 知识结构: 图1 知识结构 简单工厂模式 Sunny 软件公司欲基于 C# 语言开发一套图表库,该图表库可以为应用系统提供各种不同外观的图表,如: 柱状图(histogram) ...
- 创建型设计模式对比总结 设计模式(八)
创建型模式是new 的一种替代方式,可以将对象的创建与具体的类型进行分离 目前已经介绍了5种创建型设计模式(如果简单工厂算一种的话,那就是6种) 分别是: 简单工厂模式.工厂方法模式.抽象工厂模式.建 ...
最新文章
- PTA基础编程题目集-6-1 简单输出整数
- 光电编码器的原理及应用场合_光电传感器原理及应用
- ps -aux 状态详解
- 公共基础知识计算机,公共基础知识计算机基础知识试题
- Timequest的波形窗口调出
- SummerBoot,将SpringBoot的先进理念与C#的简洁优雅合二为一
- Apache SkyWalking的架构设计【译文】
- python场景应用方向_python的应用场景及学习方向
- 委托应用及泛型委托和多播委托
- window操作Python27
- 二、VS插件之VassistX
- SVP——一种用于深度学习的高效数据选择方法
- mysql的number范围_数据库number类型精度实用分析
- 博睿APM获《金融电子化》2021年金融业新技术应用创新突出贡献奖
- ▲什么是类?类有什么作用?
- java中xom是啥包?_XML问题,XOM Java XML API
- Java判断上海自来水来自海上_JavaAPI
- Solution to no ADO.NET in VS2019 VS里没有ADO的解决办法
- python招聘现状-python招聘现状
- 软考高级考试中有五大证书,哪个更值得考?
热门文章
- 自定义商品加入购物车动画
- 平行四边形区域均匀取样方法
- 【BUG日记】【JS】出现Cannot read property ‘xxx‘ of null
- vue中多行文本标签_element-ui+vue-cli3.0系列问题三:el-tooltip实现多行,单行文本溢出省略号处理...
- 新库上线 | CnOpenData中国星级酒店数据
- mysql netcdf_gdal联合编译C++版本proj.4、geos、hdf4、hdf5、netcdf
- Espressif-IDE ESP32 LED Flash 闪烁工程的创建
- 一千多的投影仪能用吗?哈趣、小明性价比超高的卧室投影仪
- 免费使用高性能的GPU和TPU—谷歌Colab使用教程
- 1. 从一段x86汇编程序看计算机是如何工作