领域模型的mixin模式

1.前提: 表单可以像面向对象一样继承

2.需求:
如果已有n个表单,想要额外附加统一的属性。

3.不完全解决方法:
通常的做法是,父类(表单实体)中增加对应的属性。
如果n个表单各自的父类不一样,歇菜!

4.探讨JDK mixin:
只能通过多继承模式,但java是单继承的。
还好有接口,且jdk1.8接口还支持默认方法,就是传说中的mixin。

	//通用值存取接口
	interface BaseMixin {
		default void _set(String key, Object value) {
		};

		default Object _get(String key) {
			return null;
		};
	}

	interface MyBiz1 extends BaseMixin {
		default String getName() {
			return (String) _get("name");
		}

		default void setName(String value) {
			_set("name", value);
		}
	}

	interface MyBiz2 extends BaseMixin {
		default String getTel() {
			return (String) _get("tel");
		}

		default void setTel(String tel) {

			_set("tel", tel);
		}
	}

	class Customer extends XXX implements MyBiz1, MyBiz2 {
		Map<String, Object> valueMap = new HashMap<String, Object>();

		public void _set(String key, Object value) {
			values.put(key, value);
		}

		public Object _get(String key) {
			return values.get(key);
		}
	}
这样,Customer实现了多继承。
优点:很优雅。
缺点:必须jdk1.8+,接口方法可能冲突。

5.其它mixin方式:
jdk版本小于1.8怎么办呢,mixin是形式,可用关联对象+共享数据模型达到同等效果。
问题集中在如何实现:多继承、以一处变化应万变 (设计模式的闭合原则)
思路:用属性集合引用代替多继承,因为是引用关系,就可一处修改全部生效。

案例:为所有单据增加版本信息,增加minxin属性--version。
领域模型的mixin模式_第1张图片
以后再变动,只要修改这里:
增加@Mixinable标识,仅为了开发方便,表示该实体可用做mixin属性。
领域模型的mixin模式_第2张图片

单据实体中访问Mixin属性:
mixin的所有值是存放在实体对象里面的,访问的时候转为对应的mixin接口,共享数据模型。
      
领域模型的mixin模式_第3张图片
注意处理
细节
1) mixin属性不能循环引用 
2) 属性名称冲突优先级:本类>mixin>父类,同名则覆盖
缺点:比jdk的mixin别扭
优点:It works!

6.延伸问题:继承体系下,父子同名非private属性如何覆盖?
父子类同名属性的取值,取决于访问类的声明
(与方法不一样,方法取决于实例)。
这样使用灰常不便,通常我们只要取子类的,要不也不用重复申明啊。

如何做到跟方法一样访问?思路:修改子类实例,把父类的属性引用指向子类。
但对于基础数据类型,此方法无效。
之后如果通过父类申明来使用变量,则前功尽弃。
修改的使用场合:单例、基本不动(适用于元数据定义)。
如果要动,用反射...,好bt,留着好好的属性不用,谁叫你要覆盖,谨慎还是可用的。
建议尽量用方法访问,不要用非private属性。

-------------------------------------------------------------------------------------------------------------------
关于继承实例的另一个注意点:小心静态绑定方法调用。
class A{}
class B extend A{}

访问者V
class V{
  visit(A a){}
  visit(B b){}
}

A b=new B();
v.visit(a);
将会调用
visit(A a),而不是visit(B b),这在编译期就定了,蛋疼吧。
咋办?用正确的申明在编译期绑定。

class A{
    visit(V visitor){
        visitor.visit(this);
    }
}

class B extends A{
    //不可认为A中一有就省略此方法
    visit(V visitor){
        //这里绑定visit(B)方法
        visitor.visit(this);

    }
}

A b=new A/B...(any)
a.visit(v);//将根据实例回调对应的V#visit方法。

你可能感兴趣的:(领域模型的mixin模式)