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

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

  •  
  •   Caturra ·
    caturra000 · 2019-05-11 21:39:40 +08:00 · 3484 次点击
    这是一个创建于 2017 天前的主题,其中的信息可能已经有所发展或是发生改变。
    不会画图..口头描述一下

    一个类中有多个私有的 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
    huhu3312
        1
    huhu3312  
       2019-05-11 21:42:18 +08:00 via iPhone
    策略模式试试
    HongJay
        2
    HongJay  
       2019-05-11 21:45:14 +08:00
    楼上说的没错吧
    Caturra
        3
    Caturra  
    OP
       2019-05-11 21:57:12 +08:00
    @huhu3312 一开始也想到用策略模式,但这个该怎么套用才能避免类型的判断?似乎做不到的吧
    sagaxu
        4
    sagaxu  
       2019-05-11 22:03:39 +08:00 via Android   ❤️ 1
    map<type,set>
    yehoha
        5
    yehoha  
       2019-05-11 22:05:55 +08:00
    建议看下表驱动设计模式
    arrow8899
        6
    arrow8899  
       2019-05-11 22:08:42 +08:00
    如果你要新增一种类型 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)
    huhu3312
        7
    huhu3312  
       2019-05-11 22:14:05 +08:00 via iPhone
    @Caturra 反射呀
    Caturra
        8
    Caturra  
    OP
       2019-05-11 22:18:22 +08:00
    @sagaxu
    @arrow8899

    不错的方法啊

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

    @huhu3312
    懂了 orz
    1762628386
        9
    1762628386  
       2019-05-11 22:27:55 +08:00
    没啥必要,你再优化,逻辑还是这个逻辑,顶多就是用枚举将逻辑状态和函数对应
    Corbusier
        10
    Corbusier  
       2019-05-11 22:30:38 +08:00 via iPhone
    映射啊,策略模式什么的…
    Caturra
        11
    Caturra  
    OP
       2019-05-11 23:25:25 +08:00
    @1762628386 就是想往后维护更为灵活一点,因为这些类我以后可能要用到 10 个左右,还不止一个地方,一直 if-else 不可取
    skypyb
        12
    skypyb  
       2019-05-11 23:32:26 +08:00 via Android   ❤️ 1
    要是一个类型只会有一个 set 的话(即不出现一个以上的 Set<A>) 那可以用枚举吧。
    AlisaDestiny
        13
    AlisaDestiny  
       2019-05-11 23:32:37 +08:00   ❤️ 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" 的规则;
    Yyyye
        14
    Yyyye  
       2019-05-11 23:57:08 +08:00 via Android   ❤️ 1
    我倒是觉得可以将 ab 类处理成一个接口,每个类继承这个接口,接口方法么。public int getType () 变成一个 set 接口获取的时候么,根据 type 返回
    mxalbert1996
        15
    mxalbert1996  
       2019-05-12 00:25:56 +08:00   ❤️ 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();
    }
    }
    }
    autogen
        16
    autogen  
       2019-05-12 03:26:31 +08:00
    @sagaxu 机智,送你 10 个铜板~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5589 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:33 · PVG 09:33 · LAX 17:33 · JFK 20:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.