使两个耦合类交互的最佳实践方法

时间:2018-05-17 15:55:01

标签: python class oop project-organization

我无法以面向对象的原则组织我的代码。

总结:我希望有两个单独的类,每个类都实现自己的功能(例如分别进行模拟和绘图),但不知何故将它们(以可扩展的方式!)组合成一个实例实现它们的两个功能。

示例:假设我有一个生成数据的类

class DataSimulator():
    def __init__(self, N):
        self.N = N
        self.result = None

    def simulate(self):
        self.result = range(self.N) #imagine lots of simulation code here

我还想绘制我的数据。我只需向plot()添加DataSimulator方法,但

  • 我认为DataPlotter应该是它自己独立的类,因为它的功能与DataSimulator完全不同。

A。我想出的一个选项是一个单独的类,用于存储DataSimulator个实例,然后根据需要进行绘制

class DataPlotter():
    def __init__(self, data_simulator_instance):
        self.d = data_simulator_instance

    def plot(self):
        plt.plot(self.d.result) #e.g. using matplotlib

dataSim = DataSimulator(5)
dataPlt = DataPlotter(dataSim)    
dataSim.simulate()
dataPlt.plot()

然而,为了使用这个范例;

  • 我需要始终跟踪两个独立的紧密耦合对象。这似乎是不好的做法。我永远不会有一个没有另一个,所以我想将他们的功能合二为一。

B。我认为DataPlotter继承DataSimulator就像这样:

class DataPlotter(DataSimulator):        
    def plot(self):
        plt.plot(self.result) 

dataPlt = DataPlotter(5)
dataPlt.simulate()
dataPlt.plot()

这很好,因为我现在只有一个实例可以完成我需要的一切,但这仍然是错误的,因为:

  • DataPlotter实例执行模拟例程感到困惑
  • 如果我写了DataSimulatorVersion2,我就无法重新使用DataPlotter

C。同样我也认为DataSimulator要继承DataPlotter

class DataPlotter():        
    def plot(self):
        plt.plot(self.result)  

class DataSimulator(DataPlotter):
    def __init__(self, N):
        self.N = N
        self.result = None

    def simulate(self):
        #lots of simulation code here
        self.result = range(self.N)

dataSim = DataSimulator(5)
dataSim.simulate()
dataSim.plot() 

这解决了上面的第一个问题(我认为模拟器绘制数据而不是绘图仪模拟数据是有意义的)但是现在

  • 如果我写DataSimulator
  • ,我就无法重复DataPlotterVersion2
  • self.result中使用DataPlotter而不保证变量存在也似乎是不好的做法。

我的问题:

  1. 是否有解决此问题的最佳实践方法? (我在顶部的摘要中写的实际上是我想要的,还是应该采用完全不同的路线?)
  2. 我提出的问题(在要点中)是否真的有效?

2 个答案:

答案 0 :(得分:1)

我认为列出的这些方法都不是正确的答案。模拟器用于生成数据,绘图仪旨在使用和使用它 - 数据是此处的另一个对象。绘图仪不是模拟器,模拟器不是绘图仪,理论上它们都不需要另一个存在,因此它们没有is-a或has-a关系。 OOP旨在使用对象来表示您正在使用的实际内容。我建议添加另一个Data类,即使它只是一个数组的包装器或类似的简单,你的模拟器类输出和你的Plotter类作为输入。

关于子弹 - 是的,当然 2.如果它们是紧密耦合的,考虑使用一个数据管理器的对象而不是一个名为绘图仪或模拟器的对象,从意识形态来说,它将更接近于一个对象做两件事而不是两件做一件事。如果你需要一个v2,你可以继承它并覆盖其中一个进行绘图/模拟的方法。 3,4,5,6。你是对的,出于你所描述的原因,这些都是坏主意。

答案 1 :(得分:0)

在我看来,我会像你在第一次实现中提到的那样尽可能简单:两个分开的类。 DataPlotter不仅可以绘制任何类型的数据DataSimulator,因为python不会检查您可以传递任何其他对象的类型。唯一的限制是这个对象需要一个'结果'适合' plt.plot'功能