0%

大家新年快乐。

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());
}
}

设计模式之一:观察者模式

定义:定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个 ArrayList 存放观察者们。

应用实例

  1. 拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。
  2. 西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

优点

  1. 观察者和被观察者是抽象耦合的。
  2. 建立一套触发机制。

缺点

  1. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
  2. 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  3. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景

一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
一个对象必须通知其他对象,而并不知道这些对象是谁。
需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

注意事项

  1. JAVA 中已经有了对观察者模式的支持类。
  2. 避免循环引用。
  3. 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

定义类图

例子

不使用java Observable/Observer(java 9 之后废除)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// DisplayElement.java

public interface DisplayElement {
public void display();
}



// Observer.java
public interface Observer {
public void update(double temp, double humidity, double pressure);
}



// Subject.java
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
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
// CurrentConditionsDisplay.java

public class CurrentConditionsDisplay implements Observer, DisplayElement {
private double temperature;
private double humidity;
private Subject weatherData;

public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}

@Override
public void display() {
System.out.println("Current condition: " + temperature + "F degrees and " + humidity + "% humidity");
}

@Override
public void update(double temperature, double humidity, double pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
}


//WeatherData
import java.util.ArrayList;

public class WeatherData implements Subject {
private ArrayList observers;
private double temperature;
private double humidity;
private double pressure;

public WeatherData() {
observers = new ArrayList();
}

public void measurementsChanged() {
notifyObservers();
}

public void setMeasurements(double temperature, double humidity, double pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}

@Override
public void registerObserver(Observer o) {
observers.add(o);
}

@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if(i >= 0) {
observers.remove(i);
}
}

@Override
public void notifyObservers() {
for(int i = 0; i < observers.size(); ++i) {
Observer observer = (Observer)observers.get(i);
observer.update(temperature, humidity, pressure);
}
}

public double getTemperature() {
return temperature;
}

public void setTemperature(double temperature) {
this.temperature = temperature;
}

public double getHumidity() {
return humidity;
}

public void setHumidity(double humidity) {
this.humidity = humidity;
}

public double getPressure() {
return pressure;
}

public void setPressure(double pressure) {
this.pressure = pressure;
}

}


// WeatherStation
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);

weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 32f);
}
}

使用java Observable/Observer

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
// CurrentConditionsDisplay
import java.util.Observable;
import java.util.Observer;

public class CurrentConditionsDisplay implements Observer, DisplayElement {
Observable observable;
private double temperature;
private double humidity;



public CurrentConditionsDisplay(Observable o) {
this.observable = o;
observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if(o instanceof WeatherData) {
WeatherData weatherData = (WeatherData) o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}

public void display() {
System.out.println("Current condition: " + temperature + "F degrees and " + humidity + "% humidity");
}
}


// WeatherData.java
import java.util.Observable;

public class WeatherData extends Observable {
private double temperature;
private double humidity;
private double pressure;

public WeatherData() {

}

public void setMeasurements(double temperature, double humidity, double pressure) {
this.setChanged();
notifyObservers(); // pull方法
notifyObservers("Hello"); //push 方法
}

public double getTemperature() {
return temperature;
}

public void setTemperature(double temperature) {
this.temperature = temperature;
}

public double getHumidity() {
return humidity;
}

public void setHumidity(double humidity) {
this.humidity = humidity;
}

public double getPressure() {
return pressure;
}

public void setPressure(double pressure) {
this.pressure = pressure;
}
}
1
2
3
4
5
6
7
8
9
10
11
//WeatherStation.java
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);

weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 32f);
}
}

设计模式之一:策略模式

定义: 定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让的变化独立于使用算法的客户。

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。

何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。

如何解决:将这些算法封装成一个一个的类,任意地替换。

关键代码:实现同一个接口。

应用实例

  1. 诸葛亮的锦囊妙计,每一个锦囊就是一个策略。
  2. 旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。
  3. JAVA AWT 中的 LayoutManager。

优点

  1. 算法可以自由切换。
  2. 避免使用多重条件判断。
  3. 扩展性良好。

缺点

  1. 策略类会增多。
  2. 所有策略类都需要对外暴露。

使用场景

  1. 如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
  2. 一个系统需要动态地在几种算法中选择一种。
  3. 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

1
2
3
// 针对实现编程
Dog d = new Dog();
d.bark();
1
2
3
// 针对接口编程
Animal animal = new Dog();
animal.makeSound();

实例:

解释:

衍生的特定类具有Duck共同的属性和方法,所以不能设计成为接口,应该设置成为抽象类。
叫声和飞行行为,每种鸭子行为不同,可以设置为从一系列算法族中选取一个算法。

代码:

1
2
3
4
5
6
7
8
9
10
// 算法接口
// FlyBehavior.java
public interface FlyBehavior {
void fly();
}

// QuackBehavior.java
public interface QuackBehavior {
void quack();
}
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
// 鸭子对象
// Duck.java
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;

public Duck() {}

public abstract void display();

void performQuack() {
quackBehavior.quack();
}

void performFly() {
flyBehavior.fly();
}

public void swim() {
System.out.println("I can swim");
}

public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}

public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}


// MallardDuck.java
public class MallardDuck extends Duck {

public MallardDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
// this.setFlyBehavior(new FlyWithWings());
// this.setQuackBehavior(new Quack());
}
public void display() {
System.out.println("I'm a real mallard duck");
}

public static void main(String[] args) {
MallardDuck mallardDuck = new MallardDuck();
mallardDuck.performFly();
mallardDuck.performQuack();
mallardDuck.display();

}
}

// RedheadDuck.java
public class RedheadDuck extends Duck {
@Override
public void display() {

}
}

// RubberDuck
public class RubberDuck extends Duck {
}
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
// 算法实现,即鸭子的行为
// FlyNoWay.java
public class FlyNoWay implements FlyBehavior {

@Override
public void fly() {
System.out.println("I cannot fly");
}
}

// FlyWithWings.java
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I can fly");
}
}

// MuteQuack.java
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("emmm");
}
}

// Quack.java
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Gua Gua");
}
}


// Squeak.java
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("Zhi Zhi");
}
}

今天又赖床到10点了,emmm。

起来看一会视频,吃个饭去拿风扇和我等了七天的switch,开心😊。

风扇这东西,好像是我这台电脑的通病,总是在闭合情况下打开电脑时,风扇总会发出间断性的噪声,本来以为我是以为是风扇能够检测外侧震动,从而保护自己的一种措施,没想这玩意失控,噪声相当难忍受。

拆机图:

风扇:

switch到了,等待更新中:

这是我是PDD,2279(港版主机加塞尔达),真的太香了。可惜只有单独主机,转接头、闪存、保护包还要另外买。

其他东西还在路上,不知道还要不要买个pro手柄。

今天就先这样了吧。