基于DDD模型的思考,泛型如何获取真实类型的实例对象

在这几天的探索和交流中,已找到一些解决方案,抛砖引玉,坐等更好的方案

问题

如何在使用泛型形参数的方法中,获取到泛型参数的实际类型的实例?

interface IChar{
  public <T extends IChar > void kill(T victim);
}
class A implements IChar{
  
    List<Arrow> arrows;
  
    public <T extends IChar > void kill(T victim) {
      
    }


}
class B implements IChar{
  
    List<Trun> truns;
    public <T extends IChar > void kill(T victim) {
      
    }
  
}

A、B类都有自己的个性化字段的同时实现了IChar接口,整个系统方法传递时,都是按照IChar接口将A B的实例到处传递.

下面的kill方法中 如何在不使用反射,类型强转特的情况下,获取到victim的实际类型的实例,从而拿到该实例的个性化字段<truns|arrows>?

    @Override
    public <T extends IChar > int kill(T victim) {
        return 0;
    }

有朋友说可以思考DDD充血模型
像这样

public <T extends IChar > int kill(T victim) {
        victim.kill(this);
        return 0;
    }

实际上这样传过去也是按IChar类型,如果在victim的kill中想要拿到参数的实例类型,再拿出个性化字段,也是无解的。

上面的问题,源自游戏架构设计时 遇到的问题, 塔可以攻击,人也可以攻击。
塔、人都可以相互攻击,在战斗逻辑中,除了必要的战斗参数需要拿出来运算,还可能会取出个性化字段进行逻辑上的处理,比如人是玩家操作的,他的字段可以有isvip是否是vip。。。 塔在攻击人时,如果人是vip,可以削弱一波塔的攻击力。。。

解决办法

package com.far.game.xiuzhen.gs.mgr;


import com.far.game.xiuzhen.common.database.entity.Partner;
import com.far.game.xiuzhen.gs.inherit.PartnerImpl;
import com.far.game.xiuzhen.gs.inherit.Userx;
import com.far.game.xiuzhen.gs.inherit.base.PartnerBase;

import io.netty.util.internal.InternalThreadLocalMap;
import org.apache.tomcat.jni.Thread;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

@FunctionalInterface
interface CallFunc3<X, Y, Z> {
    boolean apply(X x, Y y, Z z);
}

@FunctionalInterface
interface CallFunc1<T> {
    void apply(T e);

}

@FunctionalInterface
interface CallFunc0<T> {
    T apply();

}

@FunctionalInterface
interface CallFunc0NotR {
    void apply();

}


interface IChar {
    void kill(IChar victim);
}

interface IObject {
    String getId();

    void setVal(IChar obj);


}

/**
 * Callable 会吧所有的用到的类型都设置为字段
 * 比如 A B 类都是 他的字段
 */
public class Callable {


    private A a;
    private B b;

    private Object me;


    public Object getMe() {
        return me;
    }

    public void setMe(Object me) {
        this.me = me;
    }

    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }


    //为了方便 把A B 写成了内部类,本质都是单独的文件
    public static class A implements IChar, IObject {

        private String id = "a";
        //个性化字段
        private List<String> partner;


        public List<String> getPartner() {
            return partner;
        }

        public void setPartner(List<String> partner) {
            this.partner = partner;
        }

        @Override
        public void kill(IChar victim) {

        }

        @Override
        public String getId() {
            return id;
        }

        @Override
        public void setVal(IChar obj) {


            Callable callable = new Callable();
            callable.setA(this);
            callable.setMe(this);
            vals.put(this.id, callable);
        }


    }

    public static class B implements IChar, IObject {

        private String id = "b";
        //个性化字段
        private Map<String, Object> userx;

        public Map<String, Object> getUserx() {
            return userx;
        }

        public void setUserx(Map<String, Object> userx) {
            this.userx = userx;
        }

        @Override
        public void kill(IChar victim) {

        }

        @Override
        public String getId() {
            return id;
        }

        @Override
        public void setVal(IChar obj) {
            Callable callable = new Callable();
            callable.setB(this);
            callable.setMe(this);
            vals.put(this.id, callable);
        }


    }

    /**
     * @param killer
     * @param victim
     * @description: 战斗逻辑处理类
     * @return: void
     * @author mike/Fang.J/Q184377367
     * @date: 2022/8/3 1:03
     */
    public static <T extends IChar & IObject> void combat(T killer, T victim) {
        //killerSd 是killer的映射 killerSd内字段值的变化 影响 killer , victim同理
        Callable killerSd = vals.get(killer.getId());
        Callable victimSd = vals.get(victim.getId());

        //在该方法中实际依然不知道 killerSd victimSd的具体类型,演示中仅仅是 A B 类,实际上 C D E F .... 都会被传入
        //到该方法,所以还需要其他帮助方法 更简单的完成killer victim的类型判断和取出个性化字段


        //此处这样设计的问题:如果有几百个类都会参与到该方法 会写到手软...
        /*
            A a11 = if( A.class, victimSd.getMe,victimSd.getA)

            IF 方法 可以 简化下面这种猥琐写法
            if ( x instanof ClassA){
                ClassA aaa = (ClassA)x
            }
            ClassA aaa = IF(ClassA.class,x);

        */

//        IF(A.class, victimSd::getMe, victimSd::getA, (e) -> {
//            //如果victime是A执行特殊处理
//            //此处 参数e 已经是A类的实例
//            System.out.println("执行1");
//        });
//
//        IF(A.class, killerSd::getMe, killerSd::getA, (e) -> {
//            //如果killer是A执行特殊处理
//            //此处 参数e 已经是A类的实例
//            System.out.println("执行2");
//        });

        Compare.IF(A.class, killerSd::getMe, killerSd::getA, (e) -> {
            System.out.println("执行2");
        }).ELSE(() -> {
            System.out.println("不是");
        });


        Compare.IF(A.class, victimSd::getMe, victimSd::getA, (e) -> {
            System.out.println("执行2");
        }).ELSE(() -> {
            System.out.println("不是");
        });


        //上面的代码简化此处的判断
        if (victimSd.getMe() instanceof A) {
            String s = victimSd.getA().partner.get(0);
            int x = 1;
        } else {
            System.out.println("3");
            int b = 2;
        }


    }

    //代理方法
    public static <T extends IChar & IObject> void proxyCombat(T killer, T victim) {
        killer.setVal(killer);
        victim.setVal(victim);
        combat(killer, victim);
    }


    public static Map<String, Callable> vals = new HashMap<>();

    public static void main(String[] args) {
        proxyCombat(new A(), new B());
    }

    public static <T> void IF(Class<?> clz, CallFunc0<Object> a, CallFunc0<T> b, CallFunc1<T> func) {
        if (a.apply().getClass().getSimpleName().equals(clz.getSimpleName())) {
            func.apply(b.apply());
        }
    }


    public static class Compare<T> {

        Class<?> clz;
        CallFunc0<Object> a;
        CallFunc0<T> b;
        CallFunc1<T> trueCall;


        public void ELSE(CallFunc0NotR elCall) {
            //先执行If
            if (a.apply().getClass().getSimpleName().equals(clz.getSimpleName())) {
                trueCall.apply(b.apply());
            } else {
                elCall.apply();
            }
        }


        public static <T> Compare<T> IF(Class<?> clz, CallFunc0<Object> a, CallFunc0<T> b, CallFunc1<T> func) {
            Compare<T> ifStm = new Compare<>();
            ifStm.clz = clz;
            ifStm.a = a;
            ifStm.b = b;
            ifStm.trueCall = func;
            return ifStm;
        }

    }


}

posted @ 2022-08-02 21:04  方东信  阅读(182)  评论(0编辑  收藏  举报