Oop 面向对象设计。还有更好的吗?
我有一个Oop 面向对象设计。还有更好的吗?,oop,design-patterns,solid-principles,Oop,Design Patterns,Solid Principles,我有一个打印机类,可以打印数字和文本。对于每个客户机类,编号永远不会更改。我有更多的Client对象具有不同的number值 什么设计更好 在sample1中,数字作为参数发送到print()方法,因此所有Client对象都使用单个print对象。在sample2中,数字发送到Printer构造函数,因此每个Client对象都有自己的Printer对象 请帮我弄清楚 第二条似乎更符合您的要求 在第一种解决方案中,您使用的是“通用”打印机,它对客户机或其编号一无所知,因此需要将编号作为参数。这似乎
打印机
类,可以打印数字
和文本
。对于每个客户机
类,编号永远不会更改。我有更多的Client
对象具有不同的number
值
什么设计更好
在sample1
中,数字作为参数发送到print()
方法,因此所有Client
对象都使用单个print
对象。在sample2
中,数字发送到Printer
构造函数,因此每个Client
对象都有自己的Printer
对象
请帮我弄清楚
第二条似乎更符合您的要求
在第一种解决方案中,您使用的是“通用”打印机
,它对客户机
或其编号一无所知,因此需要将编号作为参数。这似乎是合乎逻辑的,因为在现实生活中,您可能有一台物理“打印机”,它不依赖于任何客户端
但是,您的对象模型必须符合要求,而不是“现实生活”。这有点令人困惑,因为我们有时将“需求”称为“现实生活”。无论如何,您的要求清楚地表明,客户
想要打印一些文本,对于客户来说,“数字”是静态的,即不相关。因此,只要做一个思想上的改变,打印机
不是通用打印机,而是专门为客户机
设计的打印机
有了这个心理模型,2。解决方案显然更适合您。第2项似乎更适合您的要求
在第一种解决方案中,您使用的是“通用”打印机
,它对客户机
或其编号一无所知,因此需要将编号作为参数。这似乎是合乎逻辑的,因为在现实生活中,您可能有一台物理“打印机”,它不依赖于任何客户端
但是,您的对象模型必须符合要求,而不是“现实生活”。这有点令人困惑,因为我们有时将“需求”称为“现实生活”。无论如何,您的要求清楚地表明,客户
想要打印一些文本,对于客户来说,“数字”是静态的,即不相关。因此,只要做一个思想上的改变,打印机
不是通用打印机,而是专门为客户机
设计的打印机
有了这个心理模型,2。解决方案显然更合适。我推荐解决方案1
因为如果数字不是打印机的要求,它就不应该出现在那里。如果号码是特定于客户端的,则应存储其各自的值并将其传递给打印机。这使得打印机可以在其他地方重复使用,而这些地方的数字可能会发生变化
如果您需要查询客户的号码怎么办?解决方案2使您向打印机询问特定于客户端的号码,该号码是否唯一。这不好:您违反了关注点分离。但除此之外,它感觉不平滑,对吗?解决方案2强制您重新初始化打印机,或在数字更改时创建一个新实例(如您所述)
打印机不应该关心它正在打印的内容。为了提高可重用性,可以使用“GetData()”方法使“Print()”方法接受IPrintable
。这样,打印机就不必在添加新的内容类型或内容时更改“Print()”的签名,在这种情况下,还可以避免在方法签名中使用太多参数。所以新的内容类型只是实现了IPrintable
现在您决定需要打印一个数字、一个文本和一个额外的日期或时间戳了吗?然后只需修改IPrintable
对象或创建一个新的实现,而不是修改Printer
类本身。IPrintable
对象也可以负责格式化输出。为了使它更通用,打印机不应该太在意格式化。否则,小的更改需要您安装一台新打印机
打印机通常有一个队列,允许客户端同时使用。如果将此类信息直接存储在printer对象中,则实现此功能将困难得多。代码将不再好看。最好将相关数据保存在一起,例如在IPrintable
参数中。我建议使用解决方案1
因为如果数字不是打印机的要求,它就不应该出现在那里。如果号码是特定于客户端的,则应存储其各自的值并将其传递给打印机。这使得打印机可以在其他地方重复使用,而这些地方的数字可能会发生变化
如果您需要查询客户的号码怎么办?解决方案2使您向打印机询问特定于客户端的号码,该号码是否唯一。这不好:您违反了关注点分离。但除此之外,它感觉不平滑,对吗?解决方案2强制您重新初始化打印机,或在数字更改时创建一个新实例(如您所述)
打印机不应该关心它正在打印的内容。为了提高可重用性,可以使用“GetData()”方法使“Print()”方法接受IPrintable
。这样,打印机就不必在添加新的内容类型或内容时更改“Print()”的签名,在这种情况下,还可以避免在方法签名中使用太多参数。所以新的内容类型只是实现了IPrintable
现在您决定需要打印一个数字、一个文本和一个额外的日期或时间戳了吗?然后只需修改IPrintable
对象或创建一个新的实现,而不是修改Printer
类本身。IPrintable
对象也可以是