当前位置: 首页 > 知识库问答 >
问题:

如何用界面分离原理实现多态性?

宋建本
2023-03-14

我的目标是理解接口隔离原则,同时实现多态性。

我的预期结果是:我可以用接口分离原理实现多态。

我的实际结果是:不,我不能。我被迫创建样板并使用Liskov替换原则(如果有一个Worker,必须有一个Worker不能吃,所以为Worker创建一个可以吃的扩展Worker的接口)。我想我误解了接口隔离原则。

这是违反接口隔离原则的代码。

public interface IWorker {
  void work();
  void eat();
}

class Human implements IWorker {
  public void work() {
    System.out.println("Human is working.");
  }

  public void eat() {
    System.out.println("Human is eating.");
  }
}

class Robot implements IWorker {
  public void work() {
    System.out.println("Robot is working.");
  }

  public void eat() {
    throw new UnsupportedOperationException("Robot cannot eat");
  }
}

我被告知将接口分成两部分。

public interface IEatable {
  void eat();
}

interface IWorkable {
  void work();
}

class Human implements IWorkable, IEatable {
  public void work() {
    System.out.println("Human is working.");
  }

  public void eat() {
    System.out.println("Human is eating.");
  }
}

class Robot implements IWorkable {
  public void work() {
    System.out.println("Robot is working.");
  }
}

解决方法是使用Liskov替换原理。

public interface IWorkable {
  void work();
}

interface IEatable {
  void eat();
}

interface IWorker extends IWorkable {
}

interface IHumanWorker extends IWorker, IEatable {
}

共有2个答案

林浩漫
2023-03-14

我建议使用抽象类,而不是接口。如果您需要每个都可行,那么您可以将方法抽象化。如果他们只能选择吃东西,你就不吃。例如:

abstract class Workable {

    protected String name;

    public Workable(String name) {
        this.name = name;
    }

    protected abstract void work();

    public void eat() {
        System.err.println("\"" + name + "\" can't eat");
    }
}

class Human extends Workable {
    public Human(String name) {
        super(name);
    }
    @Override
    public void work() {
        System.out.println("Human " + name + " is working!");
    }

    @Override
    public void eat() {
        System.out.println("Human " + name + " is eating!");
    }
}

class Robot extends Workable {
    public Robot(String name) {
        super(name);
    }

    public void work() {
        System.out.println("Robot " + name + " is working!");
    }
}


public class Test {
    public static void main(String[] args) {
        Workable[] workers = new Workable[] {
                new Human("Jerry"),
                new Robot("XAE12")
        };
        for (Workable worker : workers) {
            worker.work();
            worker.eat();
        }
    }
}

我不确定我是否正确理解了你的问题,所以请让我知道这是否对你有帮助。

林德华
2023-03-14

第二步看起来不错,您已经将接口拆分为两个更具体的接口。机器人“吃”是没有意义的。(我真的不懂第三步)

在调用方,您现在可以使用您的抽象:

//Polymorphism
List<IWorkable> workers = Arrays.asList(new Robot(), new Human());
//do some work

List<IEatable> eaters = Arrays.asList(new Human(), new Human());
//send for lunch break

如果你想在同一件事情上同时拥有两种行为,那么你的抽象/设计似乎是错误的,因为机器人不能根据定义进食(由未实现方法的代码气味指示)。

机器人不是IWorker(您的第一个代码),因为它不会完全满足(完整的)合同(接口、eat方法),无论它看起来有多相似。

 类似资料:
  • Liskov替代原则(LSP)和界面分离原则(ISP)之间有什么核心区别吗?最终,这两种方法都是为了设计具有通用功能的界面,并在您具有特殊功能时引入新的界面。

  • 前言 我们都知道当单库系统遇到性能瓶颈时,读写分离是首要优化手段之一。因为绝大多数系统读的比例远高于写的比例,并且大量耗时的读操作容易引起锁表导致无发写入数据,这时读写分离就更加重要了。 EF Core如何通过代码实现读写分离,我们可以搜索到很多案例。总结起来一种方法是注册一个DbContextFactory,读操作注入ReadDcontext,写操作注入WriteDbcontext;另外一种是动

  • 本文向大家介绍java中多态概念、实现原理详解,包括了java中多态概念、实现原理详解的使用技巧和注意事项,需要的朋友参考一下 一.什么是多态? 1.多态的定义 指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式(发送消息就是函数调用) 2.多态的作用 消除类型之间的耦合关系 3.多态的说明 近代网络小说泛滥,我们可以用它来举一个例子 某日你看见你手机上

  • 本文向大家介绍详解php实现页面静态化原理,包括了详解php实现页面静态化原理的使用技巧和注意事项,需要的朋友参考一下 1,file_put_contents()函数 2,使用PHP内置缓存机制实现页面静态化:output_buffering php中output_buffering内置函数,简称ob函数,主要会用到的下面几个: ob_start #打开输出控制缓冲 ob_get_contents

  • 本文向大家介绍PyQt5 如何让界面和逻辑分离的方法,包括了PyQt5 如何让界面和逻辑分离的方法的使用技巧和注意事项,需要的朋友参考一下 前言 我们已经知道利用QtDesigner来设计界面,并通过Pycharm外部工具PyUIC将其转化成py源文件。不过由于要响应事件操作,往往会将相应的槽函数写在ui的py文件中,这样,界面和逻辑开发就混合在一起了,每一次的ui更新都会伴随着转换后py文件的槽

  • 整体架构 Apache ShardingSphere 通过解析 SQL,根据配置文件中用户设置的影子规则,对传入的 SQL 进行路由并改写,删除影子字段与字段值。用户无需关注具体过程, 使用时仅对 SQL 进行相应改造,添加影子字段与相应的配置即可。 影子规则 影子规则包含影子字段及映射关系。 处理过程 以 INSERT 语句为例,在写入数据时,Apache ShardingSphere 会对 S