建议在学习设计模式之前先了解设计原则,可以参考:
传统设计模式可以分为三类:
- 创建型模式(4+1种):用于将对象的创建和使用分离,使创建对象时更加灵活可控,而不是简单地new。分为单例模式、工厂模式+抽象工厂模式、原型模式、建造者模式
- 结构型模式(7种):用于组合类和对象。分为代理模式、适配器模式、装饰者模式、桥接模式、外观模式、组合模式、享元模式
- 行为型模式(11种):用于实现对象之间的相互作用。分为模板方法模式、策略模式、命令模式、责任链模式、状态模式、观察者模式、中介者模式、迭代器模式、访问者模式、备忘录模式、解释器模式
一、创建型模式
1、单例模式
定义:确保一个类只有一个实例
分类:
- 饿汉式:类加载实例对象就创建,可以直接new、静态代码块new
- 懒汉式:首次使用对象时才会创建,可以synchronized线程安全方式、静态内部类new
应用场景:
- 类只需要单个实例:配置类,日志类,数据库连接池等
- 集中管理共享状态
饿汉式代码示例:
public class Singleton { // 饿汉式方式1 直接new
private Singleton() {} // 私有构造函数,防止直接实例化
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
public class Singleton { // 饿汉式方式2 静态代码块new
private Singleton() {}
private static Singleton instance;
static {
instance = new Singleton();
}
public static Singleton getInstance() {
return instance;
}
}
懒汉式代码示例:
public class Singleton { // 懒汉式方式1 synchronized块中new
private Singleton() {}
private static Singleton instance;
public static synchronized Singleton getInstance() { // 保证线程安全
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
public class Singleton { // 懒汉式方式2 静态内部类中new
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
解决反序列化创建对象问题:在单例类中加入readResolve()方法,反序列化时会自动调用,用于替代反序列化创建的对象
public class Singleton implements Serializable {
private static final long serialVersionUID = 1L;
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
private Object readResolve() {
return SingletonHolder.INSTANCE;
}
}
解决反射破坏单例问题:思路为在构造函数中加入检查,如果实例已经存在,则抛出异常。或者通过枚举实现单例模式
public enum Singleton { // 枚举实现单例模式
INSTANCE;
private int value;
Singleton() {
value = 6;
}
public int getValue() {
return value;
}
}
public static void main(String[] args) {
Singleton singleton = Singleton.INSTANCE;
int val = singleton.getValue();
}
2、工厂模式(抽象工厂模式)
定义:创建对象工作交给工厂类来做,我们只需要跟工厂类拿对象就好
分类:
- 简单工厂模式:if.else实现,违背开闭原则
- 工厂方法模式:接口实现
- 抽象工厂模式:类似工厂方法,但它是创建一系列相关对象。说白了你买车的时候,车本体类+智能座舱类+智驾驾驶类组成一个套餐一块买
应用场景:
- 需要创建的对象种类较多,但不确定具体是哪一种时:创建不同类型的数据库连接器MySQL、PostgreSQL等
- 需要在运行时决定创建哪种类的对象时
简单工厂模式代码示例:
public class SimpleCarFactory { // if流简单判断,后期添加新车类需要修改源代码,违背开闭原则
public static Car createCar(String type) {
Car car = null;
if("XiaomiSu7".equals(type)) {
car = new XiaomiCar();
} else if("ZhijieS7".equals(type)) {
car = new ZhijieCar();
}
return car;
}
}
工厂方法模式代码示例:
public interface CarFactory { // 后期添加新车型只需要实现接口
Car createCar();
}
public class XiaomiCarFactory implements CarFactory { // 小米汽车实现类
public Car createCar() {
return new XiaomiCar();
}
}
public class ZhijieCarFactory implements CarFactory { // 智界汽车实现类
public Car createCar() {
return new ZhijieCar();
}
}
public class CarStore { // 4S店类
private CarFactory factory;
public CarStore(CarFactory factory) {
this.factory = factory;
}
public Car orderCar() {
return factory.createCar();
}
}
抽象工厂方法代码示例:
public interface CarFactory { // 工厂接口
Car createcar();
IntelligentDriving createIntelligentDriving();
}
public class XiaomiCarFactory implements CarFactory { // 小米汽车工厂实现类
public Car createCar() {
return new XiaomiCar();
}
public IntelligentDriving createIntelligentDriving() {
return new XiaomiIntelligentDriving();
}
}
3、原型模式
定义:通过复制一个现有对象来创建新对象,而不是通过new新的对象
应用场景:
- 当需要创建对象的代价非常高时:需要初始化很多数据的大型对象
- 创建大量相似对象时:在游戏开发中,可能需要大量相似的敌人或道具
代码示例:
public class Car implements Cloneable {
public Car() {}
public Car clone() throws CloneNotSupportedException {
return (Car) super.clone();
}
}
4、建造者模式
定义:逐步构建复杂对象,其实就是Lombok中的@Builder,说白了像制作汉堡,首先选择面包,再选择肉类,最后加上配料,得到一个完整的汉堡
应用场景:
- 对象的创建过程非常复杂:创建带有CPU、内存、硬盘等的主机类
代码示例:
public class Burger { // 汉堡类
private String bread;
private String meat;
private Burger(Builder builder) {
this.bread = builder.bread;
this.meat = builder.meat;
}
public static class Builder { // 静态构建类
private String bread;
private String meat;
public Builder setBread(String bread) {
this.bread = bread;
return this;
}
public Builder setMeat(String meat) {
this.meat = meat;
return this;
}
public Burger build() {
return new Burger(this);
}
}
}
public static void main(String[] args) { // 测试
Burger burger = new Burger.Builder() // 使用建造者模式创建一个汉堡
.setBread("塔斯汀面包胚")
.setMeat("碳烤十分熟牛肉")
.build();
}
二、结构型模式
1、代理模式
定义:为一个对象提供一个代理对象以控制对某个对象的访问,说白了就是租客和房东之间的中介
分类:
- 静态代理:代理类在编译期就生成
- 动态代理:代理类在运行时动态生成,分为JDK动态代理(需要实现接口)、CGLIB动态代理(无需实现接口)
应用场景:
- 为对象提供一个代理对象来控制访问权限、进行缓存、延迟初始化等
静态代理代码示例:
public interface SellHouse { // 被代理对象接口
void sellHouse();
}
public class Landlord implements SellHouse { // 被代理对象实现类
public void sell() {
System.out.println("房东卖房");
}
}
public class ProxyPoint implements SellHouse { // 代理类
private Landlord landlord = new Landlord();
public void sell() {
System.out.println("我是中介,我想多收点钱");
landlord.sell();
}
}
JDK提供的动态代理代码示例:
public class ProxyFactory { // 代理工厂类
private Landlord landlord = new Landlord();
public SellHouse getProxyObject() {
// 参数分别为:被代理类的类加载器、被代理对象实现的接口、代理要做的事(方法)
SellHouse sellHouse = (SellHouse) Proxy.newProxyInstance(landlord.getClass().getClassLoader(),landlord.getClass().getInterfaces(),new InvocationHandler() {
// 参数分别为:代理对象、调用接口方法的Method实例、调用接口方法传递的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是中介,我想多收点钱");
Object result = method.invoke(landlord, args);
return result;
}
});
return sellHouse;
}
}
public static void main(String[] args) { // 测试
ProxyFactory factory = new ProxyFactory();
SellHouse proxyObject = factory.getProxyObject();
proxyObject.sell();
}
CGLIB动态代理代码示例:需要导包cglib.jar
public class SellHouse { // 被代理方法
public void sell() {
System.out.println("卖房子");
}
}
public class ProxyFactory implements MethodInterceptor { // 代理工厂类
private Landlord landlord = new Landlord();
public Landlord getProxyObject() {
Enhancer enhancer =new Enhancer(); // 类似JDK动态代理的Proxy类
enhancer.setSuperclass(landlord.getClass()); // 设置父类字节码对象
enhancer.setCallback(this); // 设置回调函数
Landlord obj = (Landlord) enhancer.create();
return obj;
}
// 参数分别为:代理对象、调用被代理类方法的Method实例、调用方法传递的参数、用于调用被代理类方法的代理对象
public Landlord intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("我是中介,我想多收点钱");
Landlord result = (Landlord) methodProxy.invokeSuper(obj, args);
return result;
}
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory();
SellHouse proxyObject = factory.getProxyObject();
proxyObject.sell();
}
}
2、适配器模式
定义:让由于接口不兼容而不能一起工作的类能协同工作,说白了Usb插不进Typec接口,就需要Typec-Usb转换器作为中介连接二者
分类:
- 类适配器:使用继承+实现接口组成适配器,违背聚合复用原则
- 对象适配器:耦合更低
应用场景:
- 将类的接口转换为另一个客户端能够使用的接口
类适配器代码示例:
public interface Typec { // Typec接口
String typecTransmit();
}
public class TypecImpl implements Typec { // Typec实现类
private String data = "abc";
public String typecTransmit() {
return data;
}
}
public interface Usb { // USB接口
String usbTransmit();
}
public class UsbImpl implements Usb { // USB实现类
private String data = "abc";
public String usbTransmit() {
return data;
}
}
public class Computer { // 主机类,需要兼容使用的类
public String receive(Typec typec) {
return typec.typecTransmit();
}
}
public class TypecAdapterUsb extends UsbImpl implements Typec { // 适配器类,让Computer能够调用Usb
public String typecTransmit() {
return usbTransmit();
}
}
public static void main(String[] args) { // 测试
Computer computer = new Computer();
TypecAdapterUsb adapter = new TypecAdapterUsb();
String data = computer.receive(adapter));
}
对象适配器代码示例:
public class TypecAdapterUsb implements Typec { // 适配器类
private Usb usb;
public TypecAdapterUsb(Usb usb) {
this.usb = usb;
}
public String typecTransmit() {
return usb.usbTransmit();
}
}
public static void main(String[] args) { // 测试
Computer computer = new Computer();
Usb usb = new UsbImpl();
TypecAdapterUsb adapter = new TypecAdapterUsb(usb);
String data = computer.receive(adapter));
}
3、装饰者模式
定义:在不改变对象源代码的情况下,动态地给对象加一些额外功能,说白了就像手机膜给手机屏幕加了保护功能
应用场景:
- 某些额外小功能没必要通过继承等方式实现
代码示例:
public interface Phone { // 手机接口
String getparts();
}
public class BasePhone implements Phone { // 手机类
public String getparts() {
return "本体手机";
}
}
public class ProtectiveFilmDecorator implements Phone { // 保护膜装饰器类
private Phone phone;
public ProtectiveFilmDecorator(Phone phone) {
this.phone = phone;
}
public String getparts() {
return phone.getDescription() + ", 手机膜";
}
}
public static void main(String[] args) {
Phone phone = new Phone();
Phone protectiveFilmPhone = new ProtectiveFilmDecorator(phone);
String parts = protectiveFilmPhone.getparts(); // 输出为<本体手机,手机膜>
}
4、桥接模式
定义:将抽象与实现分离,使它们可以独立变化,说白了就像汽车上的发动机,当你需要安装不同的发动机不必要修改整个汽车
应用场景:
- 需要在不修改原有代码的情况下,方便地更换、扩展功能时
代码示例:
public interface Engine { // 发动机接口
void start();
}
public class PetrolEngine implements Engine { // 汽油发动机实现类
public void start() {
System.out.println("汽油发动机,启动!");
}
}
public class DieselEngine implements Engine { // 柴油发动机实现类
public void start() {
System.out.println("柴油发动机,启动!");
}
}
public abstract class Car { // 汽车抽象类
private Engine engine;
private Car(Engine engine) {
this.engine = engine;
}
abstract void drive();
}
public class SUV extends Car { // SUV汽车类
public SUV(Engine engine) {
super(engine);
}
public void drive() {
engine.start();
}
}
public static void main(String[] args) {
Car suv = new SUV(new PetrolEngine()); // 传入需要的发动机类,后续需要修改只需要创建新的实现类
}
5、外观模式
定义:提供一个简化的接口来访问复杂的子系统,说白了像汽车你插入钥匙转一转就启动了,而不是说你先打开发动机、打开中控、打开灯光等一系列操作汽车才完全启动
应用场景:
- 屏蔽了子系统组件,让客户感受不到子系统组件
代码示例:
public class Engine { // 发动机类
void start() {
System.out.println("发动机,启动!");
}
}
public class CentralControl { // 中控类
void start() {
System.out.println("中控,启动!");
}
}
public class CarFacade { // 汽车外观模式,提供drive()一键启动发动机和中控
private Engine engine;
private CentralControl cc;
public CarFacade() {
engine = new Engine();
cc = new CentralControl();
}
public void drive() {
engine.start();
cc.start();
System.out.println("汽车启动完毕,踩油门吧!");
}
}
6、组合模式
定义:树状结构连接对象,说白了像部门以树状结构组织,可以整体管理,也可以管理其中的某个子节点
应用场景:
- 需要用到树状结构连接多个对象:文件目录等
代码示例:
public interface Employee { // 员工接口
void showEmployeeInfo();
}
public class Developer implements Employee { // 开发人员类
private String name;
public Developer(String name,) {
this.name = name;
}
public void showEmployeeInfo() {
System.out.println(name);
}
}
public class Manager implements Employee { // 经理人员类
private String name;
public Manager(String name, String id) {
this.name = name;
}
public void showEmployeeInfo() {
System.out.println(name);
}
}
public class CompanyDirectory implements Employee { // 公司目录类
private List<Employee> employeeList = new ArrayList<>();
public void addEmployee(Employee employee) { // 增加员工方法
employeeList.add(employee);
}
public void removeEmployee(Employee employee) { // 删除员工方法
employeeList.remove(employee);
}
public void showEmployeeInfo() { // 遍历调用各个员工方法
for (Employee emp : employeeList) {
emp.showEmployeeInfo();
}
}
}
public static void main(String[] args) {
Developer dev1 = new Developer("xiaoming", "001");
Developer dev2 = new Developer("lihua", "002");
Manager mgr1 = new Manager("xiaosong", "003");
CompanyDirectory devDirectory = new CompanyDirectory(); // 开发部门
devDirectory.addEmployee(dev1);
devDirectory.addEmployee(dev2);
CompanyDirectory mgrDirectory = new CompanyDirectory(); // 经理部门
mgrDirectory.addEmployee(mgr1);
CompanyDirectory companyDirectory = new CompanyDirectory(); // 公司总部门,将开发部门和经理部门纳入
companyDirectory.addEmployee(devDirectory);
companyDirectory.addEmployee(mgrDirectory);
companyDirectory.showEmployeeInfo();
}
7、享元模式
定义:共享已经存在的对象
应用场景:
- 存在大量一样的对象,可以通过共享对象来减少内存使用
代码示例:
public interface Shape { // 形状接口
void draw();
}
public class Circle implements Shape { // 圆实现类
private String color;
public Circle(String color) {
this.color = color;
}
public void draw() {
System.out.println("画" + color + "的圆");
}
}
public class ShapeFactory { // 形状工厂类
private static final Map<String, Shape> circleMap = new HashMap<>(); // 通过Map保存对象,反复利用
public static Shape getCircle(String color) {
Circle circle = (Circle) circleMap.get(color);
if (circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
}
return circle;
}
}
三、行为型模式
1、模板方法模式
定义:固定流程不变,但其中的某些步骤可以根据不同情况由不同子类来实现
应用场景:
- 整体步骤固定,但存在个别部分易变,可以抽离出来供子类实现
代码示例:
public abstract class CookingTemplate { // 做饭模板抽象类,将加配料方法抽象出来(因为可以加不同的配料)
public final void cook() { // final防止恶意操作
prepareIngredients();
startCooking();
}
abstract void prepareIngredients(); // 加配料可能不一样所以抽象,让子类实现
private void startCooking() {
System.out.println("生火起锅");
}
}
public class NoodlesCooking extends CookingTemplate { // 面条子类
protected void prepareIngredients() {
System.out.println("面条要加的配料");
}
}
public static void main(String[] args) { // 测试
CookingTemplate noodlesCooking = new NoodlesCooking();
noodlesCooking.cook();
}
2、策略模式
定义:将一系列算法封装起来,并且使它们可互相替换,说白了有几种不同的方法来解决同一个问题,可以在运行时根据需要选择其中一种方法
应用场景:
- 类在算法或行为上有不同的场景,如支付功能,可以使用支付宝、微信等
代码示例:
public interface PaymentStrategy { // 支付策略接口
void pay(int amount);
}
public class ZfbPayment implements PaymentStrategy { // 支付宝支付类
public void pay(int amount) {
System.out.println("使用支付宝支付" + amount + "元");
}
}
public class WxPayment implements PaymentStrategy { // 微信支付类
public void pay(int amount) {
System.out.println("使用微信支付" + amount + "元");
}
}
public class ShoppingPayment { // 购物支付环境类
private PaymentStrategy paymentStrategy;
public ShoppingPayment(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout(int amount) {
paymentStrategy.pay(amount);
}
}
public static void main(String[] args) { // 测试
ShoppingPayment pay = new ShoppingPayment(new ZfbPayment());
pay.checkout(100);
}
3、命令模式
定义:使发出请求的对象和执行请求的对象之间通过命令对象进行沟通,说白了遥控器可以发出增大音量、切换频道等命令,电视收到后就执行
应用场景:
- 需要将请求对象和执行对象解耦
代码示例:
public interface Command { // 命令接口,所有命令都需要实现该接口
void execute();
}
public class Audio { // 电视音频控制器类
public void up() {
System.out.println("音量调大");
}
}
public class AudioCommand implements Command { // 音频命令类
private Audio audio;
public LightOnCommand(Audio audio) {
this.audio = audio;
}
public void execute() {
audio.up();
}
}
public class RemoteControl { // 遥控器调用类
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void upAudio() {
command.execute();
}
}
public static void main(String[] args) { // 测试
Audio audio = new Audio();
Command audioUp = new LightOnCommand(Audio);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.upAudio();
}
4、责任链模式
定义:创建一个接收对象的链,请求来的时候,这些接收对象依次接收,能处理就处理,不能处理就传给下一个接收对象,直到无对象处理失败
应用场景:
- 有多个对象可以处理同一个请求,但具体处理者在运行时确定
代码示例:
public abstract class Handler { // 接收对象抽象父类
protected Handler next;
public void setNextHandler(Handler next) {
this.next = next;
}
public void handleRequest(String request) {
if (next != null) {
next.handleRequest(request);
} else {
System.out.println("没对象可以处理!");
}
}
}
public class LevelOneHandler extends Handler { // 1级接收对象子类
public void handleRequest(String request) {
if (request.equals("level-1")) {
System.out.println("我来处理...");
} else {
super.handleRequest(request);
}
}
}
public class LevelTwoHandler extends Handler { // 2级接收对象子类
public void handleRequest(String request) {
if (request.equals("level-2")) {
System.out.println("我来处理...");
} else {
super.handleRequest(request);
}
}
}
public static void main(String[] args) { // 测试
Handler level1 = new LevelOneHandler();
Handler level2 = new LevelTwoHandler();
level1.setNextHandler(level2);
basic.handleRequest("level-1");
basic.handleRequest("level-2");
basic.handleRequest("level-3"); // 无对象处理
}
5、状态模式
定义:让对象在不同状态下有不同的行为
应用场景
- 对象的行为依赖于状态,并且在运行时可以改变状态,如电梯类,上升状态、下降状态
代码示例:
public interface ElevatorState { // 电梯状态接口
void pressButton();
}
public class MovingUpState implements ElevatorState { // 电梯上升状态实现类
public void pressButton() {
System.out.println("电梯正在上升...");
}
}
public class MovingDownState implements ElevatorState { // 电梯下降实现类
public void pressButton() {
System.out.println("电梯正在下降...");
}
}
public class Elevator { // 状态管理环境类
private ElevatorState state;
public void setState(ElevatorState state) { // 改变状态
this.state = state;
}
public void pressButton() { // 根据状态执行不同方法
state.pressButton();
}
}
public static void main(String[] args) { // 测试
Elevator elevator = new Elevator();
elevator.setState(new MovingUpState());
elevator.pressButton();
elevator.setState(new MovingDownState());
elevator.pressButton();
}
6、观察者模式(发布-订阅模式)
定义:多个观察者对象监听一个主题对象,主题对象状态变化,会通知所有的观察者对象行动
应用场景:
- 多个对象需要观察某个对象的状态变化,如消息推送
- 广播系统
代码示例:
public interface Observer { // 观察者对象接口
void update(String message);
}
public class Subscriber implements Observer { // 观察者对象实现类
public Subscriber() {}
public void update(String message) {
System.out.println("接收消息:" + message);
}
}
public interface Subject { // 主题对象接口
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers(String message);
}
public class WeChatPublicAccount implements Subject { // 主题对象实现类
private List<Observer> observers;
public WeChatPublicAccount() {
observers = new ArrayList<>();
}
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
public static void main(String[] args) { // 测试
WeChatPublicAccount account = new WeChatPublicAccount();
Observer user1 = new Subscriber();
Observer user2 = new Subscriber();
account.registerObserver(user1);
account.registerObserver(user2);
account.notifyObservers("军中无细盐");
}
7、中介者模式
定义:用一个中介对象来封装一系列对象之间的交互,中介对象使各个对象不需要显示地相互引用
应用场景:
- 通过引入一个中介者对象来简化各对象之间的交互,如聊天室,所有对象通过服务器类来发送和接收消息
代码示例:
public interface Mediator { // 中介对象接口
void sendMessage(String message, User user);
}
public class ChatMediator implements Mediator { // 聊天中介对象实现类
private List<User> userList;
public ChatMediator() {
userList = new ArrayList<>();
}
public void addUser(User user) {
userList.add(user);
}
public void sendMessage(String message, User user) {
for (User u : userList) {
if (u != user) {
u.receiveMessage(message);
}
}
}
}
public abstract class User { // 用户抽象类
private Mediator mediator;
public User(Mediator mediator) {
this.mediator = mediator;
}
public abstract void sendMessage(String message);
public abstract void receiveMessage(String message);
}
public class UserBasic extends User { // 用户具体类
public UserBasic(Mediator mediator) {
super(mediator);
}
public void sendMessage(String message) {
System.out.println("发送消息: " + message);
mediator.sendMessage(message, this);
}
public void receiveMessage(String message) {
System.out.println("接收消息: " + message);
}
}
public static void main(String[] args) { // 测试
Mediator mediator = new ChatMediator();
Colleague user1 = new User(mediator);
Colleague user2 = new User(mediator);
((ChatMediator) mediator).addColleague(user1);
((ChatMediator) mediator).addColleague(user2);
user1.sendMessage("军中无细盐");
}
8、迭代器模式
定义:提供一种方法顺序访问聚合对象中的各个元素,而不暴露其内部
应用场景:
- 在不暴露集合内部结构的情况下进行遍历,如Java集合类很多使用到
代码示例:
public interface Iterator { // 迭代器接口
boolean hasNext();
Object next();
}
public class BookIterator implements Iterator { // 迭代器实现类
private List<String> books;
private int position;
public BookIterator(List<String> books) {
this.books = books;
this.position = 0;
}
public boolean hasNext() {
return position < books.size();
}
public Object next() {
if (this.hasNext()) {
return books.get(position++);
}
return null;
}
}
public class BookCollection { // 集合类
private List<String> books;
public BookCollection() {
books = new ArrayList<>();
}
public void addBook(String book) {
books.add(book);
}
public Iterator createIterator() {
return new BookIterator(books);
}
}
public static void main(String[] args) { // 测试
BookCollection collection = new BookCollection();
collection.addBook("Book 1");
collection.addBook("Book 2");
Iterator iterator = collection.createIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
9、访问者模式
定义:在不改变对象结构的情况下,定义新的操作,说白了就像导游可以给你讲解不同的景点知识,但景点本身不变
应用场景:
- 需要对对象进行许多不同且不相关的操作
代码示例:
public interface TouristSpot { // 景点接口
void accept(TourGuide guide);
}
public class Museum implements TouristSpot { // 博物馆景点实现类
public void accept(TourGuide guide) {
guide.visit(this);
}
}
public interface TourGuide { // 导游接口
void visit(Museum museum);
}
public class HistoricalTourGuide implements TourGuide { // 导游介绍景点历史实现类
public void visit(Museum museum) {
System.out.println("博物馆有这样的历史:巴拉巴拉");
}
}
public class CulturalTourGuide implements TourGuide { // 导游介绍景点文化实现类
public void visit(Museum museum) {
System.out.println("博物馆有这样的文化:巴拉巴拉");
}
}
public static void main(String[] args) { // 测试
TouristSpot spot = new Museum()
TourGuide historicalGuide = new HistoricalTourGuide();
spot.accept(historicalGuide);
TourGuide culturalGuide = new CulturalTourGuide();
spot.accept(culturalGuide);
}
10、备忘录模式
定义:在不破坏封装的前提下,保存对象内部状态,以便日后可以将对象恢复到保存的状态,说白了就像保存游戏进度,打输了就回档
分类:
- “白箱”:备忘录的内部状态对外部是可见的
- ”黑箱“:备忘录的内部状态对外部是封闭的
应用场景:
- 需要保存和恢复对象的状态
白箱代码示例:
public class Memento { // 备忘录类
public String state; // 开放
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
public class Originator { // 需要保存的对象类
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
public class Caretaker { // 备忘录管理类
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento state) {
mementoList.add(state);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
public static void main(String[] args) { // 测试
Originator originator = new Originator();
originator.setState("State1");
Caretaker caretaker = new Caretaker();
caretaker.add(originator.saveStateToMemento());
originator.setState("State666");
originator.getStateFromMemento(caretaker.get(0));
System.out.println("恢复数据: " + originator.getState());
}
黑箱代码示例:
public class Originator { // 需要保存的对象类
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
private static class Memento { // 黑箱备忘录类,内部状态只有Originator可以访问
private final String state; // 状态是私有的
private Memento(String state) { // 构造方法是私有的,只有Originator可以创建Memento
this.state = state;
}
private String getState() {
return state;
}
}
}
public class Caretaker { // 备忘录管理类
private List<Originator.Memento> mementoList = new ArrayList<>();
public void add(Originator.Memento memento) {
mementoList.add(memento);
}
public Originator.Memento get(int index) {
return mementoList.get(index);
}
}
public static void main(String[] args) { // 测试
Originator originator = new Originator();
originator.setState("State1");
Caretaker caretaker = new Caretaker();
caretaker.add(originator.saveStateToMemento());
originator.setState("State666");
originator.getStateFromMemento(caretaker.get(0));
System.out.println("恢复数据: " + originator.getState());
}
11、解释器模式
定义:把特定语法规则翻译成可执行的指令
应用场景:
- 语法较简单且需要频繁对表达式求值
代码示例:
public interface Expression { // 表达式接口
int interpret();
}
public class NumberExpression implements Expression { // 终结符表达式类
private int number;
public NumberExpression(int number) {
this.number = number;
}
public int interpret() {
return number;
}
}
public class AddExpression implements Expression { // 非终结符表达式类
private Expression leftExpression;
private Expression rightExpression;
public AddExpression(Expression leftExpression, Expression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
public int interpret() {
return leftExpression.interpret() + rightExpression.interpret();
}
}
public static void main(String[] args) { // 测试
Expression left = new NumberExpression(3);
Expression right = new NumberExpression(5);
Expression add = new AddExpression(left, right);
System.out.println("3 + 5 = " + add.interpret());
}