您如何对洗衣机进行编码?

发布于 2024-09-06 06:38:45 字数 654 浏览 3 评论 0原文

想象一下,我有一个代表简单洗衣机的类。它可以按以下顺序执行以下操作:打开->打开洗->离心机->关闭。我看到两个基本的替代方案:

  1. 我可以有一个带有方法 turnOn()、wash(int 分钟)、离心机(int revs)、turnOff() 的 WashingMachine 类。 问题是该界面没有说明正确的操作顺序。如果客户端在打开机器之前尝试离心,我最多只能抛出 InvalidOprationException 。我还可以使用一个单独的程序类,将离心机转速和洗涤分钟传递给 WashingMachine,并简化这些方法。

  2. 我可以让类本身处理正确的转换,并使用单一方法nextOperation()。另一方面,这样做的问题是语义很差。客户端不知道当他调用 nextOperation() 时会发生什么。想象一下,您实现了离心机按钮的单击事件,因此它调用了 nextOperation()。用户在机器打开后按下离心机按钮并启动!机器开始清洗。我可能需要我的类上的一些属性来参数化操作,或者可能需要一个带有washLength和centrifugalRevs字段的单独的程序类,但这并不是真正的问题。

哪种替代方案更好?或者也许还有一些我没有描述的其他更好的选择?

Imagine I have a class that represents a simple washing machine. It can perform following operations in the following order: turn on -> wash -> centrifuge -> turn off. I see two basic alternatives:

  1. I can have a class WashingMachine with methods turnOn(), wash(int minutes), centrifuge(int revs), turnOff(). The problem with this is that the interface says nothing about the correct order of operations. I can at best throw InvalidOprationException if the client tries to centrifuge before machine was turned on. I can also use a separete Program class that will pass centrifuge revs and wash minutes to the WashingMachine and will simplify these methods.

  2. I can let the class itself take care of correct transitions and have the single method nextOperation(). The problem with this on the other hand, is that the semantics is poor. Client will not know what will happen when he calls the nextOperation(). Imagine you implement the centrifuge button’s click event so it calls nextOperation(). User presses the centrifuge button after machine was turned on and ups! machine starts to wash. I will probably need a few properties on my class to parameterize operations, or maybe a separate Program class with washLength and centrifugeRevs fields, but that is not really the problem.

Which alternative is better? Or maybe there are some other, better alternatives that I missed to describe?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

灰色世界里的红玫瑰 2024-09-13 06:38:45

我有一个“高级”状态机类,它控制每个状态的进入/运行/退出(其中状态可以是“填充”、“洗涤”、“冲洗”、“清空”、“甩干”等)

绘制一个包含所有状态的状态转换图需要,包括(对于每个状态)

  1. 进入该状态之前有什么要求(进入条件)
  2. 进入该状态时需要发生什么(进入操作)
  3. 该状态期间发生什么(任务本身)
  4. 在您之前有什么要求可以离开状态(退出条件)
  5. 退出状态时会发生什么(退出操作)

您可能需要也可能不需要进入/退出条件(例如,在某些情况下您可以通过进入/退出操作强制条件)。但出于安全原因,某些条件可能是好的(例如,退出“待机”状态或进入“危险”状态,如旋转干燥)。

您还可以创建转换,它定义状态之间的链接。转换具有

  1. “从”状态
  2. 和“到”状态
  3. 转换条件(转换可以发生吗?
  4. 转换操作(转换时需要发生什么)

同样,您可能不需要所有这些,并且许多转换仅具有“ 在这

两种情况下,请尝试使每个 StateTransition 尽可能简单(尝试)为了将条件/操作放在最有意义的地方,显然可能会在 StateTransition 中定义这些条件/操作> 由于通用设计)

现在应该很明显,您可以创建一个相当通用的 State 类,其中包含所有这些事物的抽象/可重载函数,同样对于 Transition 类。State Machine 类可以根据需要调用每个成员函数,

如果您将其设置为特别通用,则 States<。 /code> 和 Transitions 可以在构造时向 State Machine 注册,或者您可以只编写 State Machine 来包含它们。

然后,您可以请求从内部状态(即特定状态可以知道它何时结束,并知道下一个状态进入哪个状态)进行转换,或者您可以有一个控制状态转换的外部类(每个状态都非常简单,纯粹照顾自己的动作,外部类决定转换的顺序和时间)。

根据我对这些事情的经验,最好将每个动作的故意顺序/计时的高级逻辑与对某些硬件事件的反应的低级逻辑分开(例如,当水位达到时从“填充”状态转换)已达到)。

不过,这是一个非常通用的设计,您可以通过多种不同的方式实现完全相同的功能 - 很少有单一正确的做事方式......

I'd have a 'high level' State Machine class which controls the entry/running/exit of each state (where states could be things like 'filling', 'washing', 'rinse', 'emptying', 'spin dry', etc)

Draw up a State Transition Diagram of all the states you need, including (for each state)

  1. what requirements there are before you enter the state (entry conditions)
  2. what needs to happen when you enter the state (entry actions)
  3. what happens during the state (the task itself)
  4. what requirements there are before you can leave the state (exit conditions)
  5. what happens when you exit the state (exit actions)

You may or may not need the entry/exit conditions (e.g. you can force the conditions with an entry/exit action in some cases). For safety reasons though, some conditions can be good (e.g. exiting from a 'standby' state or entry into a 'dangerous' state like spin dry)

You also create Transitions, which define the links between states. A transition has

  1. a 'from' state
  2. a 'to' state
  3. transition conditions (can the transition happen?
  4. transition actions (what needs to happen when you transition)

Again, you may not need all of these, and many transitions will have only the 'from' and 'to' states specified.

In both cases, try to keep each State and Transition as simple as it needs to be (try to put the conditions/actions where they make the most sense, obviously there's potential double-up of these to be defined in a State and a Transition because of the generic design)

It should be pretty obvious at this point that you can make a fairly generic State class which includes abstract/overloadable functions for all of these things, and likewise for the Transition class. The State Machine class can call each of these member functions as required, based on the transitions requested of it.

If you make it especially generic, then the States and Transitions can be registered with the State Machine at construction time, or you might just code the State Machine to contain them all.

You can then request transitions, either from within states (i.e. a particular state can know when it has ended, and know which state to go to next) or you could have an external class which controls the state transitions (each state is then very simple, purely taking care of its own actions, and the external class decides the order and timing of transitions).

In my experience with these things, it's a good idea to separate the high level logic of deliberate order/timing of each action and the low level logic of reaction to some hardware event (e.g. transition out of the 'filling' state when the water level is reached).

It's a really generic design though, and you can achieve exactly the same functionality a bunch of different ways -- there's rarely a single right way of doing things...

待"谢繁草 2024-09-13 06:38:45

我认为 turnOn()wash()centerfuge() 等应该是私有/受保护的方法。公共接口应该是doTheWash(WashMode mode)。洗衣机本身知道它支持的模式以及如何使它们工作,洗衣机的用户不需要参与操作的顺序或持续时间。期望洗衣机类的作者以合理的顺序调用私有方法是合理的。

I think that turnOn(), wash(), centerfuge() etc. should be private/protected methods. The public interface should be doTheWash(WashMode mode). The washing machine itself knows the modes it supports and how to make them work, the user of the washing machine need not get involved with the order or duration of operations. It is reasonable to expect the author of the washing machine class to call the private methods in a sensible order.

花伊自在美 2024-09-13 06:38:45

大多数西方洗衣机都使用计时器来进行循环。这个计时器可以被认为是某种状态机。然而,重要的是要认识到洗衣机是自己运行的,而不是用户运行的。用户设置初始模式,然后继续其业务。

所以在内部,你可能有 Wash、Rinse、Spin 私有函数,实际的接口是 SetCycle() 和 Start() 和 Stop()。你还可能有一些额外的属性,比如水位、搅拌速度、水温等。

开始会导致时间提前,经过一段时间后进入下一个状态,直到最后完成。

Most western washing machines use a timer to move from cycle to cycle. This timer can be thought of as a state machine of sorts. However, it's important to realize that a wasching machine runs itself, not the user. The user sets the initial mode, and then it goes on about its business.

So internally, you may have Wash, Rinse, Spin private functions, the actual interface would be SetCycle() and Start() and Stop(). You may also have some additional properties, like Water Level, Agitation Speed, Water Temperature, etc...

Start causes the time to advance, which after a period of time enters the next state, until finally it is complete.

酷到爆炸 2024-09-13 06:38:45

每台洗衣机都有一个控制器和一个程序。对于老式和简单的机器,程序和控制器被集成到相当复杂的旋钮中,现代和更昂贵的机器有一台计算机。

无论哪种情况,机器都有额外的子系统,并且控制器通知子系统执行某些操作,例如锁门将水加热至 40°C em> 或旋转鼓

控制器本身知道该序列,对于旧机器来说,该序列是相当线性和基于定时器的,而对于现代系统来说,该序列是复杂的,后者根据传感器数据改变序列。但无论哪种情况,它都会执行一系列可能通知传感器和参与者的命令。

如果您从这个角度看待洗涤系统,您可能希望利用控制器内部的命令模式来对洗涤程序进行建模,并使用观察者模式来进行通知子系统(例如:门开关监听控制器以获取锁门的信号)。

Every washing machine has a controller and a program. For older and simple machines, program and controller are integrated into a rather complicated knob, modern and more expensive machines have a computer.

In either case, the machine has additional subsystems and the controller notifies the subsystems to perform some action, like lock the door, heat water until 40°C or spin the drum.

The Controller itself knows the sequence, which is pretty linear and timer based for old machines or complex for modern systems which vary the sequence based on sensor data. But in either case it executes a series of commands which may notify sensors and actors.

If you look at the washing system from this perspective, you may want to make use of the Command pattern inside the controller to model the washing program and of the Observer pattern for notifying the subsystems (Like: The door switch listens to the controller for a signal to lock the door).

浪推晚风 2024-09-13 06:38:45

第一个正是我要做的。 washcentrifuge 将检查跟踪机器是否已打开的标志,如果未打开则抛出异常,但否则没有强制的操作顺序;如果您确实觉得有必要,可以在wash之前调用centrifuge

The first is exactly what I'd do. wash and centrifuge would check the flag that tracks if the machine is on and throw an exception if it's not, but otherwise there is no mandatory order of operations; you could call centrifuge before wash if you really felt the need

冷默言语 2024-09-13 06:38:45

嗯,有点奇怪,但就是这样;

我什至会关注代表。因此,对于特定的洗涤周期类型,如起伏、轻柔、泡沫、经济等,我会为每种洗涤周期类型提供一个接口。

然后,通过使用仿制药,我将创建我想要的适当的洗涤类型。

然后,清洗类型将具有一个清洗事件,该事件按顺序委托要执行的循环。

Erm, a little weird but here goes;

I'd be looking at even delegates. So for a particular wash cycle type, heave, light, suddsy, economic etc I'd have say an interface for each.

Then, with the use of generics, I'd create the appropriate wash type I want.

The wash type would then have a wash event which delegates, in order, the cycles to perform.

迷雾森÷林ヴ 2024-09-13 06:38:45

洗衣机应该知道如何正确运行负载。也许在清洗负载之前,需要设置某些配置项(如果未设置,则使用默认值),例如负载的类型(浅色与深色)或尺寸(小、中、大)。用户(另一个类)应该知道如何正确配置要运行的负载,但是对于洗涤负载,洗衣机应该只需要公开一个方法,例如 washLoad。在内部,它将管理何时洗大量衣物需要调用的内容。

或者,您仍然可以公开用于打开和关闭洗衣机的公共函数,那么如果在洗衣机关闭时调用 washLoad,则可以适当地抛出异常。此外,在这种情况下,我可能会通过一个方法 setLoadOptions 来设置洗衣机集,该方法将采用另一个类,例如 LoadOptions 并定义任何特征你想要可配置的。如果洗衣机没有打开,我会让这个方法也抛出异常。

The washing machine should know how to properly run a load. Perhaps before washing a load, certain configuration items are expected to be set (with defaults, if unset), like what type of load (lights vs darks) or size (small, medium, large). The user (another class) should know how to properly configure a load to run, but for washing a load, the washing machine should only need to expose one method, something like washLoad. Internally it would manage what needs to be called when to wash a load of laundry.

Alternatively, you could still expose public functions for turning the washer on and off, then if washLoad were called when the washer was off, it would be appropriate to throw an exception. Additionally, in this scenario, I would probably make the settings for the washer set via a single method setLoadOptions that would take another class the would be something like LoadOptions and defined whatever characteristics you wanted configurable. I would have this method also throw an exception if the washer was not on.

眼趣 2024-09-13 06:38:45

在我的洗衣机上,您可以使用两个旋钮。我对你的情况有什么限制有点困惑。

  1. 负载尺寸(小、中、大)
  2. 循环旋钮(烫发、针织和精致、常规)
    • 每个周期包含不同的“阶段”,可以在这些阶段激活

当您“激活”一个周期(通过转动旋钮)时,如果将其转动到周期的中间或开始,机器将开始运行。

这是一个非常非常基本的示例,说明了我如何将其转换为类:

class WashingMachine
{
    public void Activate(Cycle c, LoadSize s);
    ...
}

On my washing machine you have access to two knobs. I'm a little confused as to what the limitations are in your case.

  1. Load size (Small, Medium, Large)
  2. Cycle knob (Perm Press, Knits & Delicates, Regular)
    • Each cycle contains different "Phases" at which it can be activated at

When you "Activate" a cycle (by turning the knob), the machine will begin running if you turn it to the middle or beginning of a cycle.

Here is a really, really basic example of how I would translate this into a class:

class WashingMachine
{
    public void Activate(Cycle c, LoadSize s);
    ...
}
逆蝶 2024-09-13 06:38:45

最近,我一直在使用函数式,并使用Martin Fowler/JQuery 链接流畅风格的不可变对象。

  • 我尽可能多地使用类型系统,因为它可以进行重构。
  • 使用我的方法,编译器将强制您正确执行。
  • 由于对象在某种程度上是不可变的,因此更容易在数学上证明该状态机是确定性的。

代码:

public class Washer {
    public void exampleRun() {
        new On()
            .wash(30)
            .spin(100)
            .turnOff();
    }
    public abstract static class State {}
    public static class On extends State {
        public Wash wash(int minutes) {
            return new Wash(minutes);
        }
    }
    public static class Wash extends State {
        private int minutes;
        public Wash(int minutes) {
            super();
            this.minutes = minutes;
        }

        public Spin spin(int revs) {
            return new Spin(revs);
        }

    }
    public static class Spin extends State {
        private int revs;
        public Spin(int revs) {
            super();
            this.revs = revs;
        }
        public Off turnOff() {
            return new Off();
        }
    }
    public static class Off extends State{}
}

Lately I have been going functional and using immutable objects with Martin Fowler/JQuery chaining fluent style.

  • I use the type system as much as possible as it makes refactoring.
  • With my method the compiler will force you to do it right.
  • Because the objects are somewhat immutable its easier to prove that mathematically this state machine is deterministic.

code:

public class Washer {
    public void exampleRun() {
        new On()
            .wash(30)
            .spin(100)
            .turnOff();
    }
    public abstract static class State {}
    public static class On extends State {
        public Wash wash(int minutes) {
            return new Wash(minutes);
        }
    }
    public static class Wash extends State {
        private int minutes;
        public Wash(int minutes) {
            super();
            this.minutes = minutes;
        }

        public Spin spin(int revs) {
            return new Spin(revs);
        }

    }
    public static class Spin extends State {
        private int revs;
        public Spin(int revs) {
            super();
            this.revs = revs;
        }
        public Off turnOff() {
            return new Off();
        }
    }
    public static class Off extends State{}
}
最好是你 2024-09-13 06:38:45

选项 A 就像手动洗衣机,而选项 B 就像自动洗衣机。这两个选项对其目标用户都很有用:

选项 A 的用户可以享受手动编程整个过程(例如加倍洗涤循环,或者教小孩子如果在离心循环中关闭机器会发生什么)。

选项 B 的用户可以享受简单性并编写一个虚拟连续剧 - 在 21 秒内教你自我清洗:-)

Option A is like a manual washer while option B is like an automatic washer. Both options are useful to their targeting users:

A user of option A can enjoy manually programming the whole process (like doubling the washing circle, or teaching the little one what if you turn off the machine while it's in centrifuging circle).

A user of option B can enjoy the simplicity and write a dummy serials - teach your self washing in 21 seconds:-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文