赶紧收藏!2024 年最常见 20道设计模式面试题(七)
上一篇地址:赶紧收藏!2024 年最常见 20道设计模式面试题(六)-CSDN博客
十三、享元模式如何优化资源使用?
享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少创建对象的数量,以减少内存占用和提高性能。这种模式通过共享多于一个对象共同使用的相同状态,来优化资源使用。
享元模式的组成部分:
- 享元对象(Flyweight):享元对象是细粒度的,可以被多个客户端共享。
- 非享元对象(UnsharedConcreteFlyweight):如果有些状态不能共享,则需要创建非享元对象。
- 享元工厂(FlyweightFactory):负责创建和管理享元对象,确保享元对象可以被多个客户端共享。
享元模式的工作原理:
- 享元工厂:客户端通过享元工厂请求享元对象。享元工厂首先检查请求的享元对象是否已经存在,如果存在,则返回现有的对象;如果不存在,则创建一个新的对象。
- 享元对象:享元对象存储内部状态,这些状态对于所有共享该对象的客户端都是相同的。
- 非享元对象:如果享元对象的状态信息有部分是不可以共享的,则需要创建非享元对象来存储这些状态。
享元模式如何优化资源使用:
- 共享对象:享元模式通过共享尽可能多的对象来减少内存占用。对于具有相同内部状态的对象,享元模式只创建一个实例,然后被多个客户端共享。
- 减少对象创建:通过享元工厂来控制对象的创建,避免了不必要的对象实例化,从而减少了资源的浪费。
- 分离内部状态和外部状态:享元模式将对象的内部状态和外部状态分离。内部状态是共享的,而外部状态是特定于每个客户端的,并且不会影响其他客户端。
- 按需加载:享元模式可以实现按需加载对象,即只有在需要时才创建对象,这有助于减少启动时的资源消耗。
使用场景:
享元模式特别适用于以下情况:
- 当一个系统有大量相似对象时,这些对象的创建和维护成本很高。
- 当对象的大部分状态都可以外部化,并且可以由对象的使用者提供时。
- 当使用简单的工厂模式创建对象开销较大,或者对象的创建和销毁需要花费较多资源时。
代码示例(伪代码):
// 享元接口
interface Flyweight {void operation(String extrinsicState);
}// 具体享元对象
class ConcreteFlyweight implements Flyweight {private intrinsicState; // 内部状态,可以共享public ConcreteFlyweight(int intrinsicState) {this.intrinsicState = intrinsicState;}public void operation(String extrinsicState) {// 操作内部状态和外部状态System.out.println("Operation on intrinsic state: " + intrinsicState + " with extrinsic state: " + extrinsicState);}
}// 享元工厂
class FlyweightFactory {private HashMap<String, Flyweight> flyweights = new HashMap<>();public Flyweight getFlyweight(String key) {if (!flyweights.containsKey(key)) {flyweights.put(key, new ConcreteFlyweight(Integer.parseInt(key)));}return flyweights.get(key);}
}// 客户端代码
FlyweightFactory factory = new FlyweightFactory();
Flyweight flyweightX = factory.getFlyweight("1");
Flyweight flyweightY = factory.getFlyweight("1");flyweightX.operation("Additional information X");
// 输出: Operation on intrinsic state: 1 with extrinsic state: Additional information XflyweightY.operation("Additional information Y");
// 输出: Operation on intrinsic state: 1 with extrinsic state: Additional information Y
在这个示例中,ConcreteFlyweight
是具体的享元对象,它有一个内部状态 intrinsicState
,这个状态是共享的。FlyweightFactory
是享元工厂,它管理享元对象的创建和存储。客户端通过工厂来获取享元对象,如果对象已经存在,则工厂返回现有的对象,从而避免了重复创建。通过这种方式,享元模式优化了资源使用,减少了内存占用。
十四、请解释行为型模式中的观察者模式和状态模式的区别。
观察者模式(Observer Pattern)和状态模式(State Pattern)都是行为型设计模式,它们各自解决不同的设计问题,具有不同的结构和用途。下面是两种模式的详细解释和它们之间的主要区别:
观察者模式:
观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
特点:
- 主题(Subject)拥有一组观察者(Observer),并在状态改变时通知它们。
- 观察者模式主要用于实现分布式的事件处理系统。
组成部分:
- 主题(Subject):维护观察者列表,提供添加、删除和通知观察者的方法。
- 观察者(Observer):定义了一个更新接口,用于接收主题状态改变的通知。
使用场景:
- 当一个对象的改变需要同时改变其他对象时,且这些对象可能有很多,而且彼此之间不应该知道对方的存在。
状态模式:
状态模式允许一个对象在其内部状态改变时改变它的行为,看起来好像改变了其类。
特点:
- 状态模式通过将每个状态封装为一个类,来实现状态的转换逻辑。
- 状态模式主要用于实现状态机。
组成部分:
- 状态(State):定义了一个接口,包含一个或多个行为(方法)。
- 具体状态(Concrete State):实现状态接口,定义具体的状态行为。
- 上下文(Context):包含一个状态对象引用,负责与状态相关的行为。
使用场景:
- 当一个对象的行为取决于其状态,且它的状态值在运行时可以改变时。
观察者模式与状态模式的区别:
-
目的不同:
- 观察者模式用于对象间的通信,确保当一个对象状态改变时,所有依赖它的对象都会得到通知。
- 状态模式用于行为随状态改变而改变的场景,实现状态转换逻辑。
-
结构不同:
- 观察者模式包含主题和观察者两个主要角色,主题维护观察者列表并负责通知它们。
- 状态模式包含上下文、状态以及具体状态三个角色,上下文持有状态对象并根据状态改变行为。
-
关注点不同:
- 观察者模式关注的是如何在对象间传递消息或事件。
- 状态模式关注的是如何根据对象的状态改变其行为。
-
使用场景不同:
- 观察者模式适用于事件多播问题,如模型-视图-控制器(MVC)架构中的观察者模式。
- 状态模式适用于状态机问题,如用户界面的不同状态(如正常、暂停、退出)。
-
实现方式不同:
- 观察者模式通常通过注册和注销观察者,以及在主题中维护观察者列表来实现。
- 状态模式通常通过在上下文中维护对当前状态对象的引用,并在状态对象中实现状态转换逻辑来实现。
总结来说,观察者模式和状态模式虽然都是行为型模式,但它们的设计目的、结构组成、关注点和使用场景都有所不同。观察者模式用于对象间的事件通知,而状态模式用于根据状态改变行为。