原型模式
简述通过拷贝快速创建相同或相似对象。
接下来我们看一个需要改进的案例。
优化案例话不多说,先来看一个创建相同或相似对象的传统写法。
最初版v01234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586public class Department { private String name; private String country; private String province; private String city; private List<Employee> employees; public String getName() { return name; } public String getCount ...
建造者模式
概要创建对象时,提升属性设置的灵活性。
灵活性类中定义了大量属性时,通常为了创建对象时属性初始设置的便利随之定义大量的构造方法。为了既不定义过多的构造方法,又保证属性设置的便利性。
接下来我们看一个需要改进的案例。
对象创建的优化现在有个Employee类,如下。
最初版12345678910111213141516171819202122232425262728293031323334353637public class Employee { private String name; private String sex; private int age; private String address; // 住址 private String post; // 邮编 private String company; // 公司 private String department; // 部门 public Employee(String name, String sex, int age, ...
门面模式
简述
类型:结构型
目的:为子系统的一组接口提供统一的入口,定义了一个高层接口封装底层接口以提升系统的易用性。
废话不多说,直接看案例。
优化案例最初版v0我们都知道,网购有以下几个角色与阶段。
12345678910111213141516171819class Customer { public void start() { System.out.println("下单。。。"); } public void end() { System.out.println("收件。。。"); System.out.println("付款。。。"); }}class Shop { public void accpet() { System.out.println("确认订单。。。"); }}class Logistics & ...
设计模式六大原则
六大设计原则
单一职责原则
接口隔离原则
开闭原则
依赖倒置原则
里氏代换原则
迪米特法则
单一职责原则我们分别看两个案例,一个是遵守单一职责原则,另一个是违背。
违背的案例
1234567891011public class Computer { void calc() { System.out.println("计算数据"); // 基本功能,么得问题 } void display() { System.out.println("显示计算结果"); // 现在的计算机确实有显示功能 } void run() { System.out.println("以百米冲刺的速度奔跑"); // 这什么玩意儿?这个类到底是干嘛的 }}
遵守的案例
12345678910111213public class Computer { void calc() { ...
stream进阶
操作分类1234567graph LR 操作分类 --- 中间操作 终端操作 --- 操作分类 中间操作 --- 有状态 中间操作 --- 无状态 短路 --- 终端操作 非短路 --- 终端操作
中间操作只进行操作的记录,而实际的操作是由终端操作来执行的。如下面的例子。
张三的妈妈想让张三帮忙买调料,所以将需要购买的调料写在一张纸上交给张三。(中间操作)纸: 小葱、大蒜、生姜、鸡精、酱油。。。张三拿着纸条去买菜。(终端操作)
中间操作中间操作分为两种:有状态,无状态。
有状态:处理不止依赖当前元素。如,sorted(需要得到所有元素才可以排序不是吗)。
无状态:处理只以来当前元素。如,map(只需要对当前元素进行类型转换不是吗)。
AbstractPipeline非常重要的类,本质是个双链表,有着一下三个成员变量。Stream可以延迟执行的其中一个原因就是这个抽象类。可以说这个抽象类定义了中间操作的各种行为。
sourceStage:指向头结点。每一次中间操作会增加一个节点,为了在O(1)的时间复杂度找到头结点而定义。有点并查集的感觉。
previousSt ...
多线程入门
前置知识什么是进程,什么又是线程?咱不是讲系统,简单说下,知道个大概就好了。
进程:一个可执行文件执行的过程。线程:操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
什么是并行,什么是并发?这个也简单说下。
并行:cpu的两个核心分别执行两个线程。并发:cpu的一个核心在两个(或多个)线程上反复横跳执行。
线程的创建三种线程创建方式的优缺点以及适用场景。
继承Thread
实现Runnable
实现Callable(本文不涉及)
优点
编程简单执行效率高(就一个子类)
面向接口编程执行效率高(就一个实现类)
容器管理线程组有返回值、有异常
缺点
单继承无法有效关系线程组无返回值、无异常
无法有效关系线程组无返回值、无异常
执行效率相对较低(类间关系复杂)编程麻烦
适用场景
不推荐使用,但需要了解
简单的多线程程序
复杂业务的多线程程序推荐使用如,企业级应用
继承Thread12345678// 声明class T ex ...
泛型
泛型出现的原因Java的泛型是在JDK1.5开始才加上的。在此之前的Java是没有泛型的。没有泛型的Java使用起来给人感觉非常的笨重,为了体会泛型带来的好处,来看看如果没有泛型,我们将如何写代码,以下是样例。
12345678910111213List list = new ArrayList();list.add(1);list.add("Hello");list.add("World");list.add(2);// 现在将list中Integer类型的数据求和,并输出结果int res = 0;for (Object obj : list) { if (obj instanceof Integer) { res += (Integer)obj; }}System.out.println(res); // 输出:3
由样例我们可以看出,没有泛型 -> 可以存储任意类型 -> 使用Object类型存储 -> 取出使用时需判断并强转类型。以上流程可见其繁琐,这与 ...
lambda
学习Lambda的理由
绝大多数公司代码的主流风格。
大数据量下处理集合效率高,优秀的高并发解决。
代码的可读性增强。
消灭嵌套地狱。>形状的if或者for再也不用写了。
为了了解Lambda表达式,我们必须了解什么是函数式接口,这是Lambda表达式得以实现的依据。
在java中,函数式接口指注解了@FunctionalInterface(非必须)的接口。函数式接口具有一下特性:
接口中有且仅有一个抽象方法(必须)。
除却以上性质与普通的接口没有区别。
由以上定义,那么问题来了,为什么要使用函数式接口?
Lambda的演化让我们先看一个接口的实现案例。
朴素写法:定义实现类123456789101112131415// 传统的接口实现方式interface MyInterface { void test();}class MyInterfaceImpl implements MyInterface{ public void test() { // 各种处理 }}class Cl ...
stream入门
学习Stream的目的
函数式编程渐渐变成主流,而Stream是函数式编程的重点。
相对于传统的编程方式,代码更为简洁清晰易懂。
使得并发编程变得如此简单。
有效的避免了代码嵌套地狱。(见样例)
1234567if (条件1) { if (条件2) { if (条件3) { // 再嵌套下去都快见到Diablo了。 } }}
Stream的特点
不修改数据源:任何对于Stream对象的操作都不会修改数据源的数据。
延迟执行:中间操作只是对于一系列操作细节的定义,而非执行。只有在终端操作被调用的同时执行中间操作。
可消费:任何一个Stream对象执行了终端操作后都将不可再利用。只能操作由数据源生成的新的Stream。
Stream的分类
串行流:单项环境下的Stream,基础。
1List.of().stream(); // 获取串行流
并行流:多线程环境下的Stream,重点难点。
1List.of().parallelStream(); // 获 ...