1 工厂模式
工厂模式又分为三种:简单工厂、工厂方法、抽象工厂。
快速区分:
模式 | 概念 |
---|---|
简单工厂 | 不同产品实现相同接口,并且只有一个工厂类根据生产方法传入的参数创建不同的产品 |
工厂方法 | 工厂不止一种,实现了相同的生产接口,不同的工厂生产对应的产品 |
抽象工厂 | 工厂方法的升级,引入产品族的概念,其实就是不同工厂生产多个对应的产品 |
简单工厂:
abstract class P {
void use();
}
class P1 extends P {
void use() {...}
}
class P2 extends P {
void use() {...}
}
class F {
P create(int num) {
switch (num) {
case 1:
return new P1();
case 2:
return new P2();
}
return null;
}
}
工厂方法:
// 产品同上
// 工厂
abstract class F {
P create();
}
class F1 extends F {
P create() {
return new P1();
}
}
class F2 extends F {
P create() {
return new P2();
}
}
抽象工厂:
// 多种产品类别,每个类别下多种产品
abstract class Phone {...}
class iPhone extends Phone {...}
class MateX extends Phone {...}
abstract class Pad {...}
class iPad extends Pad {...}
class MatePad extends Pad {...}
// 工厂
abstract class F {
Phone producePhone();
Pad producePad();
}
class Apple extends F {
Phone producePhone() {
return new iPhone();
}
Pad producePad() {
return new iPad();
}
}
class Huawei extends F {
Phone producePhone() {
return new MateX();
}
Pad producePad() {
return new MatePad();
}
}
2 单例模式
单例模式又分为懒汉式和饿汉式。
快速区分:
模式 | 概念 |
---|---|
饿汉式 | 类加载时就已经创建好了唯一实例 |
懒汉式 | 调用获取实例方法时才会创建 |
对于普通的单例模式写法(即不使用静态内部类和枚举类),根据类加载机制,如果单例类还没有进行初始化(没调用过静态方法,没获取过非final的基本类型静态成员变量),饿汉式和懒汉式其实本质没什么不同。
比如下面这段饿汉式代码:
final static Product product = new Product(); private Product() { System.out.println("A product has been created."); } static Product getInstance() { return product; } } class Main { public static void main(String[] args) { System.out.println("=====main====="); System.out.println(Product.getInstance()); } }
Product的单例依然会在调用
getInstance
时才会创建,并且这个创建的线程安全由JVM保障。
而且单例模式的所有写法都是可以用一些奇怪的方式破坏的。可以用反射修改,即使是枚举类也可以用Unsafe来修改。
3 装饰者模式
套娃模式,比如JDK中的IO流使用了这种模式。
// 商品
abstract class Meal {
int cost();
}
class SimpleMeal extends Meal {
int cost() {
return 10;
}
}
class Takeaway extends Meal {
Meal Meal;
Takeaway(Meal meal) {
this.meal = meal;
}
int cost() {
return meal.cost() + 5;
}
}
4 代理模式
代理模式又分为静态代理和动态代理。
快速区分:
模式 | 概念 |
---|---|
静态代理 | 通常只代理一个类 |
动态代理 | 代理一个接口下的多个实现类 |
静态代理:
interface IssueTickets {
void countDown();
}
// 票仓放票
class TicketBunker implements IssueTickets {
int ticketLeft = 10;
public void countDown() {
ticketLeft--;
}
}
// 火车站代理售票
class TrainStation implements IssueTickets {
TicketBunker bunker = new TicketBunker();
public void countDown() {
if (bunker.ticketLeft > 0) {
bunker.countDown();
}
}
}
动态代理主要就是用JDK动态代理(通过接口)和CGLIB动态代理(通过继承)。
代理模式和装饰者模式有点像,主要区别还是在于目的:
代理模式重在控制(权限检查,日志记录等),装饰者模式重在增强(增加新的行为等)。
5 观察者模式
订阅发布模式。回调函数就是一种订阅者只有一个的观察者模式。
// 被订阅接口
interface Subject {
// 添加观察者
void addObserver(Observer o);
// 删除观察者
void removeObserver(Observer o);
// 通知所有观察者
void notifyObservers();
}
// 订阅者接口
interface Observer {
// 更新方法,接收被观察者的状态变化
public void update(String message);
}
// up主
class Up implements Subject {
// 订阅者
Set<Observer> observers = new HashSet<>();
// 最新信息
String message;
void up(String message) {
this.message = message;
notifyObservers();
}
void addObserver(Observer o) {
observers.add(o);
}
void removeObserver(Observer o) {
observers.remove(o);
}
void notifyObservers() {
for (Observer o : observers) {
o.update(message);
}
}
}