OO:容器是否包含自行车或椅子?

TMO*_*TTM 5 java oop

容器可以包含属于人的自行车和椅子.我想检查,如果容器包含自行车或所述人的椅子.没有使用这可能instanceof吗?

public class Container {

    public Map<Person, List<Item>> items = new HashMap<>();

    public void add(Person p, Item item) {
        items.get(p).add(item);
    }

    public boolean containsChair(Person owner) {
        for(Item i : items.get(owner)) {
            if(i instanceof Chair) {
                return true;
            }
        }
        return false;
    }

    public boolean containsBike(Person owner) {
        for(Item i : items.get(owner)) {
            if(i instanceof Bike) {
                return true;
            }
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

出于说明的目的,Item,Bike,Chair,Person都是最简单的类存根:

public class Person { public String name; }
public abstract class Item {}
public class Bike extends Item { public Wheel[] wheels;}
public class Chair extends Item { public Leg[] legs;}
public class Wheel {}
public class Leg {}
Run Code Online (Sandbox Code Playgroud)

在跑步者中,一个人应该能够在其容器中添加椅子和自行车:

import java.util.ArrayList;

public class Runner {
    public static void main(String[] args) {
        Container c = new Container();
        Person p = new Person();

        // Prevent null pointer exception
        c.items.put(p, new ArrayList<>());

        c.add(p, new Chair());

        // True
        System.out.println(c.containsChair(p));
    }
}
Run Code Online (Sandbox Code Playgroud)

LuC*_*Cio 5

您可以向类中添加Item一个抽象方法ItemType getType().ItemType将是枚举所有可能的项类型的枚举.

public abstract class Item {
    public abstract ItemType getType();
}

public enum ItemType {
    BIKE, CHAIR;
}
Run Code Online (Sandbox Code Playgroud)

执行Chair:

public static class Chair extends Item {
    public Leg[] legs;
    @Override
    public ItemType getType() {
        return ItemType.CHAIR;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以定义一个contains搜索给定的方法,Person如果它有一个具有某个特定的项目ItemType:

public boolean contains(Person owner, ItemType itemType) {
    return items.get(owner).stream().anyMatch(item ->itemType.equals(item.getType()));
}
Run Code Online (Sandbox Code Playgroud)

或者关于owners items列表的空安全:

public boolean contains(Person owner, ItemType itemType) {
    return Optional.ofNullable(items.get(owner))
            .map(i -> i.stream().anyMatch(item -> itemType.equals(item.getType())))
            .orElse(false);
}
Run Code Online (Sandbox Code Playgroud)

用法:

public static void main(String[] args) {
    Container c = new Container();
    Person p = new Person();

    // Prevent null pointer exception
    c.items.put(p, new ArrayList<>());

    c.add(p, new Chair());

    // True
    System.out.println(c.contains(p, ItemType.CHAIR));        
}
Run Code Online (Sandbox Code Playgroud)

编辑
按照这种方法,不需要instanceof检查.使用instanceof可以是一个提示,表明该设计有一些缺陷.


Spo*_*ted 1

您可以将Bike和存储Chair在两种不同的数据结构中。

public final class Container {
    private final Map<Person, List<Chair>> chairs = new HashMap<>();
    private final Map<Person, List<Bike>> bikes = new HashMap<>();

    public void add(Person p, Chair chair) {
        chairs.putIfAbsent(p, new ArrayList<Chair>());
        chairs.get(p).add(chair);
    }

    public void add(Person p, Bike bike) {
        bikes.putIfAbsent(p, new ArrayList<Bike>());
        bikes.get(p).add(bike);
    }

    public boolean containsChair(Person owner) {
        return chairs.getOrDefault(owner, Collections.emptyList()).size() > 0;
    }

    public boolean containsBike(Person owner) {
        return bikes.getOrDefault(owner, Collections.emptyList()).size() > 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我还创建了实例字段private来隐藏数据存储在 a 中的事实Map,并避免运行程序代码有责任实例化ArrayListif 不存在的情况。类及其字段也是final为了实现更好的不变性。在进行 OOP 时,封装和不变性都被认为是良好的实践。

用法

public static void main(String[] args) {
    Container c = new Container();
    Person p = new Person();
    c.add(p, new Chair());
    System.out.println(c.containsChair(p)); //true
    System.out.println(c.containsBike(p)); //false
}
Run Code Online (Sandbox Code Playgroud)