0%

不好意思好久没更新了。

我三月七号回的杭州,在自如上,在公司旁边租了小房子,自我隔离了七天。

还算是比较贵,6.4平、公共厨房、公共卫生间,一天60。不过也没办法短租不太好找,一个月工资全拿来交房租了(难受

三月十六号开始真正回公司上班。

工作的同时还伴随着完成毕设.. 每天都很焦躁. (疯狂拖延症),拖着拖着一天就结束了,啥事都没做成(难受。

复试大概是要拖到五月了,应该还有时间吧。

今天就到这里吧,尽量每个月都更新一点。

八方旅人,一方五十

第一次全通关一款JRPG,断断续续打了一个月,将近80小时全收集。

这个主线剧情最终Boss和隐藏Boss难度跨度有点大。

全角色第四章通关之后,花了5、6天准备升级和职业搭配准备打最后的隐藏Boss(PS:不愧是非酋之舞,不然也不会刷5天的级)

打完隐藏Boss之后整一个八方旅人的八个零散的主线就可以织起来了,总的剧情中规中矩。

游戏机制在老式传统回合制上有创新,玩起来有功有防,很有节奏感。同时音乐出色,不过价格偏贵,switch版玩完还可以回血。

推荐程度8/10

最后收藏了一些图:

不好意思,差不多一个多月没有更新了。

因为疫情,没法回杭州了。当然我这边已经开始远程办公了,从2月初就开始了,开始了差不都三星期了。

基本上每天早上9点起来,吃个早餐,开始工作。晚上打麻将,然后switch 1-2小时。毕设根本不想动……

考研成绩也已经出了,考的比较一般吧,还是有机会进复试的,现在好好准备复试吧。之后等复试结束,录取名单出了,再总结一下考研历程吧。

写这篇随笔的目的,主要是准备转换生活方式了。

今年上半年的的三座大山:

  • 研究生复试
  • 毕设
  • 实习

希望这三个都能好好的完成。

就到这里吧。

大家新年快乐。

19号坐的的动车回来,还好没赶上疫情爆发的时候。

这几天舆论发酵的厉害,其实也没必要过度惊慌,武汉1000多万人,就算实际感染的人数有几千人,其实中奖几率也就是万分之一。但是也不能过度放松。必要的带带口罩,勤洗手其实就够了。

希望一切都会好起来。

忙了一星期,准备在年前完成实习生工作的寻找,现在已经入职两天了。这还是很紧要的,毕竟我们学校有4个实习的必修学分,实习期必须满3个月。

找工作唯一的感觉,就是感觉学的不够深入,虽然接触了大部分东西,但大部分都是浅尝辄止。都说今年是互联网企业的寒冬,但是这样也得硬着头皮上了。如果实在找不到的话,就在老师的手下做实习生吧。

忘了说我的进的是虹软科技,测试开发实习生,可惜没有开发岗位了。

已经实习两天了,感觉还不错,公司氛围挺好的,其他的以后再说说吧。

设计模式之一:命令模式

定义:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数话其他对象。命令模式也支持可撤销的操作。

主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

何时使用:在某些场合,比如要对行为进行”记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将”行为请求者”与”行为实现者”解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

如何解决:通过调用者调用接受者执行命令,顺序:调用者→接受者→命令。

关键代码:定义三个角色:

  1. received 真正的命令执行对象
  2. Command
  3. invoker 使用命令对象的入口

应用实例:struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的 Command。

优点

  1. 降低了系统耦合度。
  2. 新的命令可以很容易添加到系统中去。

缺点:使用命令模式可能会导致某些系统有过多的具体命令类。

使用场景:认为是命令的地方都可以使用命令模式,比如:

  1. GUI 中每一个按钮都是一条命令。
  2. 模拟 CMD。

注意事项:系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式,见命令模式的扩展。

类图

设计模式之一:单例模式

定义:确保一个类只有一个实例,并提供一个全局访问点。

主要解决:一个全局使用的类频繁地创建与销毁。

何时使用:当您想控制实例数目,节省系统资源的时候。

如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

关键代码:构造函数是私有的。

应用实例

  1. 一个班级只有一个班主任。

  2. Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。

  3. 一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
    优点:

  4. 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。

  5. 避免对资源的多重占用(比如写文件操作)。
    缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

使用场景

  1. 要求生产唯一序列号。
  2. WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  3. 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
    注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

优点:单件可以延迟实例化。

类图

典型代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 多线程情况下,如果性能对应用程序不是很关键,可以加上synchronized, 不过可能回造成执行效率下降100倍。
// 延迟实例化
public class Singleton {
private static Singleton uniqueInstance;

private Singleton() {}

public static synchronized Singleton getInstance() {
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
1
2
3
4
5
6
7
8
9
10
// “急切”创建实例。
public class Singleton {
private static Singleton uniqueInstance = new Singleton(); // 保证线程安全

private Singleton() {}

public static Singleton getInstance() {
return uniqueInstance;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

public class Singleton {
// 双重检查加锁
private volatile static Singleton uniqueInstance;

private Singleton() {
}

public static Singleton getInstance() {
if(uniqueInstance == null) {
synchronized (Singleton.class) {
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}

}

设计模式之一:工厂模式

简单工厂

不是一个真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦。

工厂方法模式

定义:定义了一个创建对象的接口,但由子类决定要实例化的类事哪一个。工厂方法让类把实例化推迟到子类。

主要解决:主要解决接口选择的问题。

何时使用:我们明确地计划不同条件下创建不同实例时。

如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。

关键代码:创建过程在其子类执行。

应用实例

  1. 您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
  2. Hibernate 换数据库只需换方言和驱动就可以。

优点

  1. 一个调用者想创建一个对象,只要知道其名称就可以了。
  2. 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
  3. 屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

使用场景

  1. 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
  2. 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
  3. 设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。

注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

类图

设计模式之一:抽象工厂模式

定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

主要解决:主要解决接口选择的问题。

何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。

如何解决:在一个产品族里面,定义多个产品。

关键代码:在一个工厂里聚合多个同类产品。

应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。

优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

使用场景

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

注意事项:产品族难扩展,产品等级易扩展。

类图

设计模式:设计原则

  1. 找出应用中可能需要变化指出,把它们独立出来,不要和那些不需要变化的代码混在一起。

  2. 针对接口编程,而不是针对实现编程。

  3. 多用组合,少用继承。

    针对接口编程,即针对超类型编程,也就是使用多态。

  4. 为了交互对象之间的松耦合设计而努力。

  5. 开放-关闭原则:类应该对拓展开放,对修改关闭。

  6. 依赖倒置原则:要依赖抽象,不要依赖具体类。

    变量不可以持有具体类的引用。
    不要让类派生自具体类。
    不要覆盖基类中已实现的方法。

设计模式之一:装饰者模式

定义:动态地将责任附加到对象上。若要拓展功能,装饰者提供了比继承更有弹性的替代方案。

主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

何时使用:在不想增加很多子类的情况下扩展类。

如何解决:将具体功能职责划分,同时继承装饰者模式。

关键代码

  1. Component 类充当抽象角色,不应该具体实现。
  2. 修饰类引用和继承 Component 类,具体扩展类重写父类方法。

应用实例

  1. 孙悟空有 72 变,当他变成”庙宇”后,他的根本还是一只猴子,但是他又有了庙宇的功能。
  2. 不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。

优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:多层装饰比较复杂。

使用场景

  1. 扩展一个类的功能。
  2. 动态增加功能,动态撤销。

注意事项:可代替继承。

实例

代码

抽象类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Beverage.class

public abstract class Beverage {
String description = "Unknown bean.Beverage";

public String getDescription() {
return description;
}

public abstract double cost();
}

// CondimentDecorator.java

public abstract class CondimentDecorator extends Beverage{

public abstract String getDescription();
}

具体组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// DarkRoast.class

public class DarkRoast extends Beverage {
@Override
public double cost() {
return 1.5;
}

public DarkRoast() {
description = "darkRoast";
}
}


// Decaf.java
public class Decaf extends Beverage {
@Override
public double cost() {
return .67;
}

public Decaf() {
description = "bean.Decaf";
}
}

// Espresso.java
public class Espresso extends Beverage {
@Override
public double cost() {
return 1.99;
}

public Espresso() {
description = "Espresso";
}
}

// HouseBlend.java
public class HouseBlend extends Beverage {
@Override
public double cost() {
return .89;
}

public HouseBlend() {
description = "House Blend Coffee";
}
}

// Milk.java
public class Milk extends CondimentDecorator {
Beverage beverage;

public Milk(Beverage beverage) {
this.beverage = beverage;
}

@Override
public String getDescription() {
return beverage.getDescription() + ", Milk";
}

@Override
public double cost() {
return 0.5 + beverage.cost();
}
}

// Mocha.java
public class Mocha extends CondimentDecorator {
Beverage beverage;

public Mocha(Beverage beverage) {
this.beverage = beverage;
}

@Override
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}

@Override
public double cost() {
return .20 + beverage.cost();
}
}

// Soy.java
public class Soy extends CondimentDecorator {
Beverage beverage;

public Soy(Beverage beverage) {
this.beverage = beverage;
}

@Override
public String getDescription() {
return beverage.getDescription() + ", Soy";
}

@Override
public double cost() {
return 0.7 + beverage.cost();
}
}

// Whip.java
public class Whip extends CondimentDecorator {
Beverage beverage;

public Whip(Beverage beverage) {
this.beverage = beverage;
}

@Override
public String getDescription() {
return beverage.getDescription() + ", Whip";
}

@Override
public double cost() {
return 0.8 + beverage.cost();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

// StarbuzzCoffee.java
public class StarbuzzCoffee {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());

Beverage beverage1 = new DarkRoast();
beverage1 = new Mocha(beverage1);
beverage1 = new Mocha(beverage1);
beverage1 = new Whip(beverage1);
System.out.println(beverage1.getDescription() + " $" + beverage1.cost());

Beverage beverage2 = new HouseBlend();
beverage2 = new Soy(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
}
}