自学内容网 自学内容网

巧用设计模式:Apollo 打造高效稳健的配置管理体系

在当今的软件开发领域,设计模式如同建筑大师手中的蓝图,能够帮助开发者更高效、更稳健地构建复杂的软件系统。Apollo 配置中心作为一款在微服务架构中广泛应用的配置管理利器,巧妙地运用了多种设计模式,如责任链模式、单例模式、观察者模式、工厂模式、外观模式、策略模式。今天,我们就来结合源码,逐一揭秘这些设计模式在 Apollo 中的应用。

1. 单例模式

应用场景

在整个应用程序运行期间,只需要一个实例的类,采用单例模式可以确保全局只有一个实例,节省资源,方便全局访问。

源码分析

  • 客户端
    ConfigService类是获取配置的入口,它内部维护了一个ConfigManager的单例实例,用于管理Config对象。
public class ConfigService {
    private static final ConfigService s_instance = new ConfigService();
    private volatile ConfigManager m_configManager;
    private volatile ConfigRegistry m_configRegistry;

    public ConfigService() {
    }
// 用到了单例模式,懒加载
    private ConfigManager getManager() {
        if (this.m_configManager == null) {
            synchronized(this) {
                if (this.m_configManager == null) {
                    this.m_configManager = (ConfigManager)ApolloInjector.getInstance(ConfigManager.class);
                }
            }
        }

        return this.m_configManager;
    }
// 用到了单例模式,懒加载
    private ConfigRegistry getRegistry() {
        if (this.m_configRegistry == null) {
            synchronized(this) {
                if (this.m_configRegistry == null) {
                    this.m_configRegistry = (ConfigRegistry)ApolloInjector.getInstance(ConfigRegistry.class);
                }
            }
        }
        return this.m_configRegistry;
    }
}

2. 工厂模式

应用场景

工厂模式用于创建对象,将对象的创建和使用解耦,客户端不需要知道具体的创建过程。

源码分析

  • 客户端
    ConfigManager负责创建和管理Config对象,不同的命名空间可能需要不同的Config实例
public class DefaultConfigManager implements ConfigManager {
    private ConfigFactoryManager m_factoryManager = (ConfigFactoryManager)ApolloInjector.getInstance(ConfigFactoryManager.class);
    private Map<String, Config> m_configs = Maps.newConcurrentMap();
    private Map<String, ConfigFile> m_configFiles = Maps.newConcurrentMap();

    public Config getConfig(String namespace) {
        Config config = (Config)this.m_configs.get(namespace);
        if (config == null) {
            synchronized(this) {
                config = (Config)this.m_configs.get(namespace);
                if (config == null) {
                // 获取工厂类
                    ConfigFactory factory = this.m_factoryManager.getFactory(namespace);
                    // 使用工厂类根据namespace创建具体的配置类
                    config = factory.create(namespace);
                    this.m_configs.put(namespace, config);
                }
            }
        }

        return config;
    }

3. 观察者模式(Observer Pattern)

应用场景

当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。Apollo需要在配置发生变化时通知客户端或其他组件。

源码分析

  • 客户端
    Config接口提供了addChangeListener方法,允许注册监听器,当配置变化时,通知所有的监听器
public interface Config {
    void addChangeListener(ConfigChangeListener listener);
    String getProperty(String key, String defaultValue);
}

DefaultConfig在内部维护了一个ConfigChangeListener的列表,当配置变化时,遍历并通知所有的监听器。

public class DefaultConfig implements Config {
      private final List<ConfigChangeListener> m_listeners = Lists.newCopyOnWriteArrayList();


    @Override
    public void addChangeListener(ConfigChangeListener listener) {
        m_listeners.add(listener);
    }

    private void fireConfigChange(ConfigChangeEvent changeEvent) {
        for (ConfigChangeListener listener : m_listeners) {
            listener.onChange(changeEvent);
        }
    }
}

4. 策略模式

应用场景

策略模式允许在运行时选择算法的实现。Apollo在配置加载、序列化等场景中,通过策略模式选择不同的实现。

源码分析:

  • 客户端
    ConfigFileFormat枚举了不同的配置文件格式,如Properties、XML、JSON等,不同的格式对应不同的解析策略。
public enum ConfigFileFormat {
      Properties("properties"), XML("xml"), JSON("json"), @Deprecated YML("yml"), YAML("yaml"), TXT("txt");

}

ConfigFileFactory根据不同的格式,创建对应的ConfigFile实现类。

public class ConfigFileFactory {
    public static ConfigFile create(String namespace, ConfigFileFormat format) {
        switch (format) {
            case Properties:
                return new PropertiesConfigFile(namespace);
            case XML:
                return new XmlConfigFile(namespace);
            // 其他格式
            default:
                throw new IllegalArgumentException("Unsupported format: " + format);
        }
    }
}

5. 外观模式

应用场景

外观模式为子系统中的一组接口提供了一个一致的界面,使得子系统更容易使用。ConfigService就是一个外观,为客户端提供简单的配置获取接口。

源码分析

  • 客户端
    ConfigService对外提供静态方法,隐藏了内部的复杂实现。
public class ConfigService {
    public static Config getAppConfig() {
        return getConfig(ConfigConsts.NAMESPACE_APPLICATION);
    }

    public static Config getConfig(String namespace) {
        return getInstance().getConfig(namespace);
    }

    // 内部实现细节
}

6. 责任链模式

应用场景

责任链模式将请求沿着处理者链传递,直到有处理者处理它。

源码分析

  • 服务端:

在Apollo服务端,有多个不同的 ReleaseMessageListener 实现类。每个实现类负责处理特定的发布消息类型或执行特定的业务逻辑。当一个发布消息被接收时,Apollo会根据责任链的逻辑,依次调用这些实现类的 handleMessage 方法。

/**
   * Notify listeners with messages loaded
   * @param messages
   */
  private void fireMessageScanned(Iterable<ReleaseMessage> messages) {
    for (ReleaseMessage message : messages) {
      for (ReleaseMessageListener listener : listeners) {
        try {
        // 责任链
          listener.handleMessage(message, Topics.APOLLO_RELEASE_TOPIC);
        } catch (Throwable ex) {
          Tracer.logError(ex);
          logger.error("Failed to invoke message listener {}", listener.getClass(), ex);
        }
      }
    }
  }

总结

Apollo配置中心的源码中,使用了如上多种设计模式,包括但不限于单例模式、工厂模式、观察者模式、策略模式等。这些设计模式的应用,提高了系统的灵活性和可维护性,方便扩展和修改。同时,也体现了面向对象设计中的重要原则,如开闭原则、单一职责原则、依赖倒置原则等。


原文地址:https://blog.csdn.net/weixin_45593273/article/details/144324853

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!