设计模式概述 - 建造者 & 观察者 & 抽象工厂 & 状态
建造者模式简述
建造者模式(Builder Pattern)是一种创建型设计模式,它通过使用多个简单的对象一步步构建一个复杂的对象。建造者模式允许用户使用相同的构建过程创建不同的表示,适用于需要创建复杂对象的场景。
角色
- 产品(Product):表示被构建的复杂对象。
- 建造者接口(Builder):定义创建产品的各个部分的接口。
- 具体建造者(ConcreteBuilder):实现建造者接口,构建并返回产品的实例。
- 指挥者(Director):负责管理建造过程,调用建造者的方法。
优点
- 分离复杂对象的构建与表示:建造者模式将对象的构建过程与表示分离,使得同样的构建过程可以创建不同的表示。
- 提高代码可读性:通过使用建造者模式,代码的结构更加清晰,易于理解和维护。
- 灵活性:可以通过不同的建造者创建不同的产品。
缺点
- 增加复杂性:引入建造者模式可能会导致类的数量增加,从而增加系统的复杂性。
- 不适合简单对象:对于简单对象的创建,使用建造者模式可能显得过于复杂。
示例代码
// 产品类
class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
@Override
public String toString() {
return "Product{" +
"partA='" + partA + '\'' +
", partB='" + partB + '\'' +
", partC='" + partC + '\'' +
'}';
}
}
// 建造者接口
interface Builder {
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}
// 具体建造者
class ConcreteBuilder implements Builder {
private Product product = new Product();
@Override
public void buildPartA() {
product.setPartA("Part A");
}
@Override
public void buildPartB() {
product.setPartB("Part B");
}
@Override
public void buildPartC() {
product.setPartC("Part C");
}
@Override
public Product getResult() {
return product;
}
}
// 指挥者
class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Product product = builder.getResult();
System.out.println(product);
}
}
观察者模式简述
观察者模式(Observer Pattern)是一种行为型设计模式,定义了一种一对多的依赖关系,使得当一个对象(主题)状态发生变化时,所有依赖于它的对象(观察者)都会得到通知并自动更新。该模式常用于实现事件处理系统。
角色
- 主题(Subject):被观察的对象,维护观察者的列表并提供注册和注销观察者的方法。
- 观察者(Observer):对主题的变化作出反应的对象,通常定义一个更新方法。
- 具体主题(ConcreteSubject):实现主题接口,维护状态并通知观察者。
- 具体观察者(ConcreteObserver):实现观察者接口,更新自身状态以反映主题的变化。
优点
- 松耦合:观察者与主题之间的关系是松耦合的,观察者不需要知道主题的具体实现。
- 动态关系:可以在运行时动态添加或移除观察者,灵活性高。
- 促进广播通信:主题可以一次性通知所有观察者,简化了通信过程。
缺点
- 可能导致过多通知:如果观察者数量较多,可能会导致性能问题,因为每次状态变化都需要通知所有观察者。
- 观察者依赖:如果观察者未能正确处理更新,可能导致系统的不一致性。
- 复杂性增加:在某些情况下,观察者模式可能导致系统的复杂性增加,特别是在观察者和主题之间的关系较为复杂时。
示例代码
import java.util.ArrayList;
import java.util.List;
// 主题接口
interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}
// 观察者接口
interface Observer {
void update(String message);
}
// 具体主题
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
notifyObservers();
}
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
}
// 具体观察者
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received update: " + message);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserver observer1 = new ConcreteObserver("Observer 1");
ConcreteObserver observer2 = new ConcreteObserver("Observer 2");
subject.attach(observer1);
subject.attach(observer2);
subject.setState("State 1");
subject.setState("State 2");
}
}
抽象工厂模式简述
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。抽象工厂模式适用于需要创建多个相关对象的场景,能够提高代码的灵活性和可扩展性。(可以使用反射+配置文件的形式优化if判断)
角色
- 抽象工厂(AbstractFactory):定义创建抽象产品的方法。
- 具体工厂(ConcreteFactory):实现抽象工厂,创建具体的产品对象。
- 抽象产品(AbstractProduct):定义产品的接口。
- 具体产品(ConcreteProduct):实现抽象产品,定义具体的产品。
优点
- 封装性:抽象工厂模式将具体类的实例化过程封装起来,客户端只需依赖于抽象接口。
- 易于扩展:增加新产品时,只需新增具体工厂和具体产品,原有代码无需修改,符合开放-封闭原则。
- 一致性:确保产品的一致性,避免产品之间不兼容的问题。
缺点
- 类的数量增加:每增加一种产品系列,就需要增加相应的具体工厂和具体产品类,可能导致类的数量激增。
- 复杂性:在某些情况下,使用抽象工厂模式可能会使系统变得复杂,尤其是在产品族较多时。
示例代码
// 抽象产品A
interface ProductA {
void use();
}
// 具体产品A1
class ConcreteProductA1 implements ProductA {
@Override
public void use() {
System.out.println("Using ConcreteProductA1");
}
}
// 具体产品A2
class ConcreteProductA2 implements ProductA {
@Override
public void use() {
System.out.println("Using ConcreteProductA2");
}
}
// 抽象产品B
interface ProductB {
void use();
}
// 具体产品B1
class ConcreteProductB1 implements ProductB {
@Override
public void use() {
System.out.println("Using ConcreteProductB1");
}
}
// 具体产品B2
class ConcreteProductB2 implements ProductB {
@Override
public void use() {
System.out.println("Using ConcreteProductB2");
}
}
// 抽象工厂
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.use();
productB1.use();
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.use();
productB2.use();
}
}
状态模式简述
状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态改变时改变其行为。状态模式将状态的相关行为封装在独立的状态类中,使得对象的行为随着状态的改变而改变,从而避免使用大量的条件语句。
角色
- 上下文(Context):维护一个对具体状态对象的引用,并定义客户端可以使用的接口。
- 状态接口(State):定义一个接口,用于封装与上下文的一个特定状态相关的行为。
- 具体状态(ConcreteState):实现状态接口,定义与上下文的一个特定状态相关的行为。
优点
- 简化代码:通过将状态相关的行为封装在状态类中,减少了条件语句的使用,从而简化了代码。
- 易于扩展:新状态的添加不需要修改现有代码,只需新增具体状态类,符合开放-封闭原则。
- 状态独立:每个状态都可以独立变化,状态之间的逻辑清晰,易于理解。
缺点
- 类的数量增加:每个状态都需要一个具体状态类,可能导致类的数量增加,增加系统复杂性。
- 状态切换复杂:在某些情况下,状态之间的切换逻辑可能会变得复杂,尤其是状态依赖关系较多时。
示例代码
// 状态接口
interface State {
void handle(Context context);
}
// 具体状态A
class ConcreteStateA implements State {
@Override
public void handle(Context context) {
System.out.println("Handling request in State A.");
context.setState(new ConcreteStateB()); // 切换到状态B
}
}
// 具体状态B
class ConcreteStateB implements State {
@Override
public void handle(Context context) {
System.out.println("Handling request in State B.");
context.setState(new ConcreteStateA()); // 切换到状态A
}
}
// 上下文
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
Context context = new Context(new ConcreteStateA());
context.request(); // 处理请求并切换到状态B
context.request(); // 处理请求并切换回状态A
}
}