- , 28 9月 2021
- 作者 847954981@qq.com
- 后端学习
设计模式
设计模式是前程序员总结出来的最佳实践,结果时间沉淀,形成的一套解决问题的方法。
通常,一个设计模式专注于解决一类问题,不会有万能的设计模式
单例模式
当数据对象存在 唯一 现象
如一个班级只有一个班主任,则使用单例模式,即保证一个类仅有一个实例
单例模式的核心办法是把构造函数设置为私有:
代码语言:javascript复制public class ClassMaster {
private String id;
// 班主任名称
private String name;
private String gender;
// 唯一实例
private static ClassMaster instance = new ClassMaster();
private ClassMaster() {
}
}
再在自己类的内部实例化自己,以此不允许其他类实例化这个类,只有自己能实例化一个唯一的自己。
此时,我们需要添加一个get方法来获取这个实例
代码语言:javascript复制 public static ClassMaster getInstance() {
return instance;
}
简单工厂模式
简单工厂模式解决的问题是:代码重复、耦合紧密
如以水果商店为例,为满足不同口味顾客,商店需要根据口味单独将单个水果实例化如(伪代码)
代码语言:javascript复制public class 餐馆 {
public static void main(String[] args) {
if (客人.get口味() == "甜") {
西瓜 w = new 西瓜();
} else if (客人.get口味() == "酸") {
柠檬 l = new 柠檬();
} else if (客人.get口味() == "臭") {
榴莲 d = new 榴莲();
}
}
}
而这样的情况可以使用简单工厂模式代替
简单工厂模式例子:
代码语言:javascript复制public class FruitFactory {
public static Fruit getFruit(Customer customer) {
Fruit fruit = null;
if ("sweet".equals(customer.getFlavor())) {
fruit = new Watermelon();
} else if ("acid".equals(customer.getFlavor())) {
fruit = new Lemon();
} else if ("smelly".equals(customer.getFlavor())) {
fruit = new Durian();
}
return fruit;
}
}
这样来完成代码,可以更有效完成解耦以及解决代码重复问题
工厂类为了提高辨识度,一般以 XXXFactory为名
抽象工程模式
简单工厂适合创建一种对象,但当情况复杂,需要创建一个系列、多种产品的时候,就需要抽象工厂模式。
如水果超市除了卖水果,还需要提供饮料,需要在“水果工厂”之外创建一个“饮料工厂”,我们可以多创建一个工厂抽象类把多个工厂进一步抽象。
其中由于水果工厂需要继承接口,需要添加getDrink()方法,此时返回null就行
SnacksFactoryBuilder 方法是生产工厂的工厂,如工厂是生产产品的工厂,其作用是创建工厂实例。
观察者模式
观察者模式的核心是要知道观察什么,什么对象发生了变化需要发出通知,如天气系统的订阅/通知功能。
如天气系统,我们需要观察的是天气的变化,我们抽象出天气的对象,
代码语言:javascript复制public class WeatherData extends Observable
让它继承Java提供的 Observable 类,表示其是核心的、需要被观察的类。被称为被观察者
如
代码语言:javascript复制public class WeatherData extends Observable {
// 城市
private String cityName;
// 时间
private String time;
// 温度
private String temp;
// 城市固定了就不变了
public WeatherData(String cityName) {
this.cityName = cityName;
}
// 打印天气信息
public String toString() {
return cityName "," LocalDate.now().toString() " " time ",气温:" temp "摄氏度。";
}
public String getCityName() {
return cityName;
}
public String getTime() {
return time;
}
public String getTemp() {
return temp;
}
}
然后我们需要在数据变化后发起通知:
代码语言:javascript复制public class WeatherData extends Observable {
/**
* 一个城市的气温在某个时刻发生了变化
*/
public void changeTemp(String time, String temp) {
if(time == null || temp == null) {
// 输入数据为空是有问题的,不处理
return;
}
// 与原数据不同,说明发生了变化
if(!time.equals(this.time) || !temp.equals(this.temp)) {
// 标记变化
super.setChanged();
this.time = time;
this.temp = temp;
// 发出通知,参数是额外的信息
super.notifyObservers("温度变化已通知");
}
}
}
这里使用了父类方法 setChanged() 和 notifyObservers()
setChanged() 是标记被观察者对象发生了变化
notifyObservers() 就是发出通知,如果需要发生额外(不在观察者对象内)的信息,在参数中传入信息对象即可。
存在被观察者,自然也要创建观察者:
代码语言:javascript复制public class WeatherObserver implements Observer {
private String name;
@Override
public void update(Observable o, Object arg) {
System.out.print(this.name "观察到天气变化为:");
System.out.print(o.toString());
System.out.println(" " arg);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
观察者需要实现 update() 方法其中,
方法第一个参数是被观察者对象(继承Observable)
方法第二个参数就是额外信息,具体就是调用 super.notifyObservers()
时传入的参数对象。
如果不想发生额外信息,就是 super.notifyObservers(null)
此时arg值就是null。
当我们在 main中调用时,被观察者需要添加观察者:
代码语言:javascript复制 // 城市天气数据
WeatherData weatherData = new WeatherData("余杭");
// 添加观察者
weatherData.addObserver(w1);
weatherData.addObserver(w2);