设计模式-策略工厂

这篇具有很好参考价值的文章主要介绍了设计模式-策略工厂。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在介绍策略工厂的实现前,我们要先了解spring中beanFactory:

BeanFactory

作为IOC服务的提供者,通过XmlBeanFactory来得到实例

生产Bean的工厂,采用延迟初始化策略(只有在需要某个对象时,才进行初始化和依赖注入);通常会用xml文件来注册并管理各个业务对象之间的依赖关系

DefaultListableBeanFactory实现了BeanFactory接口和BeanDefinitionRegistry接口(负责Bean的注册管理)
设计模式-策略工厂

属性键值对注入PropertyValue

这里的key:group,value:name

位于beans包下,是bean属性键值对的封装,缓存了对key-value解析相关的信息,避免重复解析

设计模式-策略工厂

  • AttributeAccessor 可以访问对象的属性或将属性附加到对象上。
public interface AttributeAccessor {
	//增删改查
	void setAttribute(String name, @Nullable Object value);
	@Nullable
	Object getAttribute(String name);
	@SuppressWarnings("unchecked")
	default <T> T computeAttribute(String name, Function<String, T> computeFunction) {
		Assert.notNull(name, "Name must not be null");
		Assert.notNull(computeFunction, "Compute function must not be null");
		Object value = getAttribute(name);
		if (value == null) {
			value = computeFunction.apply(name);
			Assert.state(value != null,
					() -> String.format("Compute function must not return null for attribute named '%s'", name));
			setAttribute(name, value);
		}
		return (T) value;
	}
	@Nullable
	Object removeAttribute(String name);
	boolean hasAttribute(String name);
	String[] attributeNames();
}
  • BeanMetadataElement 持有属性信息的对象。
public interface BeanMetadataElement {

	@Nullable
	default Object getSource() {
		return null;
	}

}
  • BeanMetadataAttributeAccessor 实现了 AttributeAccessor和 BeanMetadataElement 两个接口,属性为 BeanMetadataAttribute 对象
public class BeanMetadataAttributeAccessor extends AttributeAccessorSupport implements BeanMetadataElement {

	@Nullable
	private Object source;

	public void setSource(@Nullable Object source) {
		this.source = source;
	}

	@Override
	@Nullable
	public Object getSource() {
		return this.source;
	}
}
  • PropertyValue 属性键值对
public class PropertyValue extends BeanMetadataAttributeAccessor implements Serializable {
	//属性名称
	private final String name;
	//属性值
	@Nullable
	private final Object value;
	//属性值是否是optional
	private boolean optional = false;
	//属性值是否进行了属性转换
	private boolean converted = false;
	//类型转换后的属性值
	@Nullable
	private Object convertedValue;
	//属性值是否需要进行转换
	@Nullable
	volatile Boolean conversionNecessary;
	//缓存解析后的属性名称
	@Nullable
	transient volatile Object resolvedTokens;

MutablePropertyValues

设计模式-策略工厂

PropertyValues的默认实现类是MutablePropertyValues

MutablePropertyValues:

  • 内部维护了一个List<PropertyValue> propertyValueList将属性值转换为PropertyValue进行存储
    Bean的结构图:
    设计模式-策略工厂
    每一个受管的对象,在容器中都会有一个BeanDefinition的实例与之对应,BeanDefinition存储对象的信息,包括:

  • 对应的对象的class类型,是否抽象类,构造方法参数及其他信息

  • beanName就是实例名

实现策略工厂:

注解StrategyAnnotation

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface StrategyAnnotation {
    /**
     * 策略类型名称,可以支持多个
     *
     * @return
     */
    String[] name() default "";

    /**
     * 默认组为: defaultGroup
     *
     * @return
     */
    String group() default "defaultGroup";

    /**
     * 是否默认类型
     *
     * @return
     */
    boolean isDefault() default false;
}

创建策略工厂实现类

管理所有的方法

/**
 * 策略工厂
 * 当你使用注解 StrategyAnnotation 在类上面
 * 那么会通过 RegisterMapDefinition 去自动创建策略工厂。
 *
 * 策略工厂的名称就是 StrategyAnnotation 定义的group.
 *
 * 支持的state 参数,就是 StrategyAnnotation 定义的 name
 *
 */
public class StrategyFactory<T> {
    //key是策略类型,value是具体策略
    Map<String, T> localMap;

    public T getObjectByState(String state) {
        return localMap.get(state);
    }

    public T defaultObject(String state) {
        T t = localMap.get(state);
        if (t == null) {
            t = localMap.get(null);
        }
        return t;
    }

    public T getObjectThrowException(String state) {
        T t = localMap.get(state);
        if (t == null) {
            throw new IllegalStateException("获取对象失败,状态:" + state);
        }
        return t;
    }

    public void setLocalMap(Map<String, T> localMap) {
        this.localMap = localMap;
    }

    public Map<String, T> getLocalMap() {
        return Collections.unmodifiableMap(this.localMap);
    }
}

RegisterMapDefinition

自动创建策略工厂文章来源地址https://www.toymoban.com/news/detail-500803.html

  1. 获取注解的group
  2. 首次registry这个groupBean
  3. 获取这个groupBean的BeanDefinition
  4. 遍历注解的name
  5. 通过定义的key(localMap)获得PropertyValue属性值
  6. 首次属性值为空,创建一个PropertyValue(以localMap为key,ManagedMap为value)
  7. 将localMap这个PropertyValue属性添加到propertyValues中即可
/**
 * 策略配置加载器
 */
@Component
public class RegisterMapDefinition implements BeanDefinitionRegistryPostProcessor {

    public static final String LOCAL_MAP_PROPERTY = "localMap";
    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 本文加载有注解的bean为map 作为策略映射,
     *
     * @param beanFactory
     * @throws BeansException
     * @see StrategyAnnotation
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }

    private void registerGroupMap(BeanDefinitionRegistry registry, StrategyAnnotation strategyAnnotation, String beanName, BeanDefinition beanDefinition) {
        String groupBean = strategyAnnotation.group();
        if (!registry.containsBeanDefinition(groupBean)) {
            RootBeanDefinition strategyFactoryDefinition = new RootBeanDefinition();
            strategyFactoryDefinition.setBeanClass(StrategyFactory.class);
            registry.registerBeanDefinition(groupBean, strategyFactoryDefinition);
        }
        BeanDefinition groupBeanDefinition = registry.getBeanDefinition(groupBean);

        String[] names = strategyAnnotation.name();
        for (String name : names) {
            MutablePropertyValues propertyValues = groupBeanDefinition.getPropertyValues();
            PropertyValue localMap = propertyValues.getPropertyValue(LOCAL_MAP_PROPERTY);
            if (localMap == null) {
                localMap = new PropertyValue(LOCAL_MAP_PROPERTY, new ManagedMap<>());
                propertyValues.addPropertyValue(localMap);
            }
            ManagedMap<TypedStringValue, BeanReference> stringObjectManagedMap =
                    (ManagedMap<TypedStringValue, BeanReference>) localMap.getValue();
            stringObjectManagedMap.put(new TypedStringValue(name), new RuntimeBeanReference(beanName));
            if (strategyAnnotation.isDefault()) {
                stringObjectManagedMap.put(null, new RuntimeBeanReference(beanName));
            }
            propertyValues.addPropertyValue(localMap);
        }
    }


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        String op = "RegisterMapDefinition.postProcessBeanDefinitionRegistry";
        logger.info(Logs.op(op).msg("批量创建策略实例").toString());
        //获取所有的beanName
        String[] strategyAnnotationsArray = registry.getBeanDefinitionNames();
        //遍历每个beanName
        for (String beanName : strategyAnnotationsArray) {
            BeanDefinition beanDefinition = registry.getBeanDefinition(beanName);
            try {
                //获得bean的类名
                String beanClassName = beanDefinition.getBeanClassName();
                if (beanClassName == null) {
                    continue;
                }
				//找到类对象
                Class<?> clazz = Class.forName(beanClassName);
                //获取类对象上的StrategyAnnotations注解
                StrategyAnnotations annotation = AnnotationUtils.findAnnotation(clazz, StrategyAnnotations.class);
                //有StrategyAnnotations注解的进行注册
                if (annotation != null) {
                    for (StrategyAnnotation strategyAnnotation : annotation.value()) {
                        registerGroupMap(registry, strategyAnnotation, beanName, beanDefinition);
                    }
                }

                StrategyAnnotation strategyAnnotation = AnnotationUtils.findAnnotation(clazz, StrategyAnnotation.class);
                if(strategyAnnotation!=null){
                    registerGroupMap(registry, strategyAnnotation, beanName, beanDefinition);
                }

            } catch (ClassNotFoundException e) {
                logger.debug(Logs.op(op).msg("策略加载器加载指定类不存在").toString(), e);
            }

        }
    }
}

到了这里,关于设计模式-策略工厂的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++ 程序设计:四大模式(工厂+装饰+策略+观察者)

    \\\"工厂+装饰+策略+观察者\\\"是常见且常用的设计模式之一,但并不是指称\\\"四大模式\\\"的官方术语。 \\\" 四大模式 \\\"通常是指指令式面向对象编程中的四个基本概念: 封装 、 继承 、 多态 和 抽象 。这四个概念是面向对象编程的基石。 工厂模式( 例:工厂方法模式 )中,通常存在

    2024年02月17日
    浏览(45)
  • 【java设计模式】创建型模式介绍(工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式)

    简介 本文介绍Java设计模式中创建型模式的五种 一、工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 工厂模式提供了一种将对象的实例化过程封装在工厂类中的方式。通过使用工

    2024年02月16日
    浏览(45)
  • 设计模式-简单工厂模式(静态工厂模式)java实现

    简单工厂模式根据所 提供的参数 数据返回几个可能类中的一个类的实例。通常返回的类都有一个公共的父类和公共的方法。   意图 提供一个类,负责根据一定的条件创建某一具体类的实例。同时使用工厂模式也是为了隐藏创建对象的过程 角色及其职责 (1)工厂(Creator)角色

    2024年02月13日
    浏览(52)
  • 【创建型设计模式】C#设计模式之工厂模式,以及通过反射实现动态工厂。

    题目如下: 简单工厂实现: 上述代码给出了抽象基类的基本定义,和泛型工厂的实现方式,以及调用方式。 值得注意的是 where T : Car, new() 这个条件: where T : Car, new() 是对泛型类型参数 T 的约束。这个约束表明泛型类型参数 T 必须满足两个条件: T 必须是 Car 类或者其派生类

    2024年02月11日
    浏览(40)
  • [设计模式Java实现附plantuml源码~创建型] 多态工厂的实现——工厂方法模式

    前言: 为什么之前写过Golang 版的设计模式,还在重新写 Java 版? 答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。 为什么类图要附上uml 因为很多人学习有做笔记的习惯,如果单纯的只是放一张图片,那

    2024年01月21日
    浏览(42)
  • Python入门【​编辑、组合、设计模式_工厂模式实现 、设计模式_单例模式实现、工厂和单例模式结合、异常是什么?异常的解决思路 】(十七)

    👏作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白 📕系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀 🔥如果感觉博主的文章还不错的

    2024年02月14日
    浏览(42)
  • 【设计模式】Head First 设计模式——工厂方法模式 C++实现

    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使得一个类的实

    2024年02月10日
    浏览(47)
  • 【设计模式】Head First 设计模式——抽象工厂模式 C++实现

    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定他们具

    2024年02月10日
    浏览(39)
  • 【设计模式】使用 go 语言实现简单工厂模式

    最近在看《大话设计模式》,这本书通过对话形式讲解设计模式的使用场景,有兴趣的可以去看一下。 第一篇讲的是 简单工厂模式 ,要求输入两个数和运算符号,得到运行结果。 这个需求不难,难就难在类要怎么设计,才能达到可复用、维护性强、可拓展和灵活性高。 运

    2024年02月05日
    浏览(44)
  • [设计模式Java实现附plantuml源码~创建型] 集中式工厂的实现~简单工厂模式

    前言: 为什么之前写过Golang 版的设计模式,还在重新写Java 版? 答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。 为什么类图要附上uml 因为很多人学习有做笔记的习惯,如果单纯的只是放一张图片,那

    2024年01月19日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包