首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  程序员

求解一个简单的 if-else 优化问题

  •  
  •   Caturra · 43 天前 · 1819 次点击
    这是一个创建于 43 天前的主题,其中的信息可能已经有所发展或是发生改变。
    不会画图..口头描述一下

    一个类中有多个私有的 Set,分别对应不同的类型,但这多个类型都有共同的接口(也就是说基本都差不多一个样),用于存放分别对应类型的对象

    现在我要设计一个方法,接收该接口的类型,方法内部调用相对应的 Set,如何避免多个 if-else ?

    --手动分割--

    由于语死早,所以还是用个具体的过程再描述一遍

    比如说一个 class 有 3 个 Set,分别是私有的 Set<A> a,Set<B> b,set<C> c,其中 A,B,C 都是接口 I 的实现类
    简化的方法声明:xjbfunction(I obj)
    简化的内部实现:
    if(obj instanceof A) a.add(obj);
    if(obj instanceof B) b.add(obj);
    c 同理
    //以上是 java 的写法

    现在我想把 if-else 换成一个更简化通用的写法去表示,该如何去做(因为往后要扩展出更多的类和更复杂的业务处理),补充下次要要求:Set 尽量不要暴露给不必要的类

    自己实在太菜了暂时没啥头绪,大家有什么好方法可以分享一下
    16 回复  |  直到 2019-05-12 03:26:31 +08:00
        1
    huhu3312   43 天前 via iPhone
    策略模式试试
        2
    HongJay   43 天前
    楼上说的没错吧
        3
    Caturra   43 天前
    @huhu3312 一开始也想到用策略模式,但这个该怎么套用才能避免类型的判断?似乎做不到的吧
        4
    sagaxu   43 天前 via Android   ♥ 1
    map<type,set>
        5
    yehoha   43 天前
    建议看下表驱动设计模式
        6
    arrow8899   43 天前
    如果你要新增一种类型 Set<D> 还是需要改代码啊;可以用 hashmap 来保存

    LinkedHashMap<String, Set<I>> linkedHashMap = new LinkedHashMap<>();

    linkedHashMap.put(obj.getClass().getName(), new Set<I>())
    linkedHashMap.get(obj.getClass().getName()).add(obj)
        7
    huhu3312   43 天前 via iPhone
    @Caturra 反射呀
        8
    Caturra   43 天前
    @sagaxu
    @arrow8899

    不错的方法啊

    @yehoha
    头一回听说 orz。。我现在就去 Google

    @huhu3312
    懂了 orz
        9
    1762628386   43 天前
    没啥必要,你再优化,逻辑还是这个逻辑,顶多就是用枚举将逻辑状态和函数对应
        10
    Corbusier   43 天前 via iPhone
    映射啊,策略模式什么的…
        11
    Caturra   43 天前
    @1762628386 就是想往后维护更为灵活一点,因为这些类我以后可能要用到 10 个左右,还不止一个地方,一直 if-else 不可取
        12
    skypyb   43 天前 via Android   ♥ 1
    要是一个类型只会有一个 set 的话(即不出现一个以上的 Set<A>) 那可以用枚举吧。
        13
    AlisaDestiny   43 天前   ♥ 2
    ```java
    public class Test1 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    T t = new T();
    t.put(new A());
    t.put(new B());
    t.put(new A());
    t.put(new C());
    }
    }

    class T{
    private Set<? super I> aset = new HashSet<>();
    private Set<? super I> bset = new HashSet<>();
    private Set<? super I> cset = new HashSet<>();

    public void put(I item) throws NoSuchFieldException, IllegalAccessException {
    Field f = T.class.getDeclaredField(item.getClass().getSimpleName().toLowerCase() + "set");
    f.setAccessible(true);
    Object o = f.get(this);
    if(o instanceof java.util.Set){
    ((java.util.Set)o).add(item);
    }
    System.out.println("==============");
    System.out.println(aset);
    System.out.println(bset);
    System.out.println(cset);
    System.out.println("==============");
    }

    }
    interface I{
    }

    class A implements I{

    }
    class B implements I{

    }
    class C implements I{

    }
    ```
    java 无所不能,你这看下 demo 是你需要的不,传入实现了 I 接口的类,自动根据实例名字添加到对应的 set. PS:需要你 set 的命名符合 实例名.toLowerCase() + "set" 的规则;
        14
    Yyyye   43 天前 via Android   ♥ 1
    我倒是觉得可以将 ab 类处理成一个接口,每个类继承这个接口,接口方法么。public int getType () 变成一个 set 接口获取的时候么,根据 type 返回
        15
    mxalbert1996   43 天前   ♥ 1
    没必要用反射啊,假设你有 A 和 B 两个类都实现了 Interface 这个接口,那你可以这么写:

    public class Test {
    private Class[] classes = {A.class, B.class};
    private HashMap<Class, Set<Interface>> sets = new HashMap<>();

    public Test() {
    for (Class clazz : classes) {
    sets.put(clazz, new HashSet<>());
    }
    }

    public void add(Interface value) {
    Set<Interface> set = sets.get(value.getClass());
    if (set != null) {
    set.add(value);
    } else {
    throw new IllegalArgumentException();
    }
    }
    }
        16
    autogen   43 天前
    @sagaxu 机智,送你 10 个铜板~
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2152 人在线   最高记录 5043   ·   Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 18ms · UTC 11:03 · PVG 19:03 · LAX 04:03 · JFK 07:03
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1