java中装饰器和状态模式的结合——关于OO设计的问题
我正在解决一个问题,我认为它最适合装饰器和状态模式。高级设置类似于三明治机和分配器,其中我有一定数量的原料和我可以制作的几种不同类型的三明治。每种成分都有与其相关的成本。客户将使用机器选择制作特定三明治的原料,然后机器会分配它。
到目前为止,我已经使用装饰器模式创建了成分和不同类型的三明治:
public abstract class Sandwich {
String description = "Unknown Sandwich";
public String getDescription(){
return description;
}
public double cost(){
return 0.0;
}
}
每种成分都建模如下:
public abstract class Ingredient extends Sandwich {
public abstract String getDescription();
}
更进一步,具体成分将是:
public class Cheese extends Ingredient {
private Sandwich sandwich;
public Cheese(Sandwich sandwich){
this.sandwich = sandwich;
}
public String getDescription() {
return sandwich.getDescription() + ", cheese";
}
public double cost() {
return 0.25 + sandwich.cost();
}
}
特定类型的三明治可以建模如下:
public class BLT extends Sandwich {
public BLT(){
description = "Bacon, Lettuce and Tomato";
}
}
所以客户将创建一个像这样的特定三明治:
Sandwich order_a_blt = new Tomato(new Lettuce(new Bacon(new Bread(new BLT()))));
下一步,我将创建一个分配器对象,它将充当自动机器,它预先加载了特定数量的成分(以通用单位测量),用户可以按用于选择预设选项之一的按钮:
例如
- BLT:1 单位番茄,1 单位 生菜、培根 1 单位、面包 1 单位
- SUB:肉丸 1 单位、奶酪 1 单位、 1 单位意大利酱、1 单位面包
- 等。
我的分配器机器将预装每种成分的固定数量单位
- 番茄:10
- 生菜:10
- 培根:10
- 等。
以及供用户选择特定种类的按钮列表三明治:
- 1-BLT
- 2-SUB
- 3-BBQ
- ..etc
这个想法是跟踪成分的内部容量,并能够告诉用户,比如说,我们
现在 没有足够的培根来制作另一个 BLT ,我最初的想法是基于状态设计模式创建 Dispenser 对象,但我在尝试将 Ingredient 类的对象与 Dispenser 类中的某种存储结合起来时遇到了问题。首先,我通过一张带有名称/值的地图来配对成分类型/成分数量。但我不确定如何将这些模式组合在一起,以便我可以在每次使用后自动递减。
您是否对如何继续实施这样的概念有一个总体想法?首先,我的装饰器和状态模式是否走在正确的轨道上?是否有更有效的方法?我希望我已经清楚地解释了这个问题。
谢谢你的任何指导,我很感激任何想法
I am in the middle of solving a problem where I think it's best suited for a decorator and a state pattern. The high level setting is something like a sandwich maker and dispenser, where I have a set amount of ingredients and a few different types of sadnwiches i can make. Each ingedient has a cost associated with it. The client would be someone who will use the machine to select ingredients to make a particular swndwich and the machine would dispense it.
So far I have created the ingredients and the different types of sandwiches using the decorator pattern:
public abstract class Sandwich {
String description = "Unknown Sandwich";
public String getDescription(){
return description;
}
public double cost(){
return 0.0;
}
}
Each ingredient is modeled this this:
public abstract class Ingredient extends Sandwich {
public abstract String getDescription();
}
And further more, a concrete ingredient would be:
public class Cheese extends Ingredient {
private Sandwich sandwich;
public Cheese(Sandwich sandwich){
this.sandwich = sandwich;
}
public String getDescription() {
return sandwich.getDescription() + ", cheese";
}
public double cost() {
return 0.25 + sandwich.cost();
}
}
A specific type of a sandwich can be modeled like this:
public class BLT extends Sandwich {
public BLT(){
description = "Bacon, Lettuce and Tomato";
}
}
So a client would create a specific sandwich like this:
Sandwich order_a_blt = new Tomato(new Lettuce(new Bacon(new Bread(new BLT()))));
As a next step I will create a Dispenser object which will act as an automatic machine, which is pre-loaded with a specific number of ingredients (which are measured in generic units) and a user can press a button to choose one of the pre-set selections:
For example
- BLT: 1 unit of tomato, 1 unit of
lettuce, 1 unit bacon, 1 unit bread - SUB: 1 unit meatballs, 1 unit cheese,
1 unit italian_sauce, 1 unit bread - etc..
My Dispenser machine will come preloaded with a fixed number of units per ingredient
- tomato: 10
- lettuce: 10
- bacon: 10
- etc..
And a list of buttons for the user to select a specific kind of sandwich:
- 1-BLT
- 2-SUB
- 3-BBQ
- ..etc
The idea is to keep track of the internal capacity of ingredients and be able to tell the user that, say, we don't have enough bacon left to make another BLT
Now, my initial thought is do create the Dispenser object based on the state design pattern, but I have hit a problem trying to combine the objects of the Ingredient class with some kind of a storage within the Dispenser class. At first I though a map with name/value pairs the ingredient type/ingredient quantity. But I am not sure how to combine those patterns together so I can decrement automatically after every use.
Do you perhaps have a general idea on how to go ahead and implement such a concept? First of all am I on the right track with decorator and state patterns? Would there be a more efficient approach? I hope I have explained the problem clearly.
Thank you for any direction, I appreciate any thoughts
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Sandwich 与 Cheese 是“has-a”关系,因此 Sandwich 永远不应该是 Cheese 的父代。
不确定您在这一行做什么:
从逻辑上讲,为什么要创建一个 Tomato 对象并向其传递一个 Lettuce?
番茄、生菜...等应添加成分。
我会像这样
在每个成分类中,我会在Tomato中放置一个静态变量,将其称为tomatoCount,然后在创建分配器时初始化它,每次创建新的Tomato时都会递减它。如果它达到零,那么番茄类就会抱怨
The Sandwich to Cheese is "has-a" relation, so Sandwich should never be a parent of Cheese.
Not sure what you are doing at this line:
Logically speaking, why would you create a Tomato object and passing it a Lettuce?
Tomato, Lettuce .... etc should extend Ingredient.
I would make it like this
Inside each ingredient class, i would put a static variable, in Tomato, would call it tomatoCount, then initialize it when creating the Dispenser, each time a new Tomato is created would decrement it. If it reach zero then Tomato class would complain
运行时描述基于其
成分而不是硬编码它
在班级层面;
关于三明治;
所以,我会提供以下解决方案:
description in runtime based on its
ingredients instead of hardcoding it
at class level;
about sandwiches;
So, I'd offer the following solution:
装饰器模式不适合您的问题。成分不会向三明治添加新行为,更不用说以is-a关系链接三明治和(三明治)成分已经有点做作了。 (嵌套实例化只有在必须动态执行之前才看起来很酷。)
三明治有配料/馅料/调味品。为成分建立一个类层次结构,并使用复合模式将它们与三明治折叠在一起。
另外,我认为状态模式对于分配器没有用,因为它与配料或三明治的管理有关。该模式规定了对象的内部使用来改变类的行为。但分配器不需要基于状态的多态行为:
例如,分配器的内部状态没有显着变化,因此其公共接口需要多态行为。
The decorator pattern is not appropriate to your problem. An Ingredient does not add new behaviour to a Sandwich, never mind that linking a Sandwich and a (sandwich) Ingredient in a is-a relationship is already a tad contrived. (Nested instantiation only looks cool until you have to do it dynamically.)
A Sandwich has Ingredients/Fillings/Condiments. Establish a class hierarchy for the Ingredients and fold them together with the Sandwich using the Composite Pattern.
Too, I do not think the State pattern is useful for the Dispenser as it relates to the management of Ingredients or Sandwiches. The pattern prescribes the internal use of objects to change the behaviour of a class. But the DIspenser does not need polymorphic behaviour based on state:
e.g., the Dispenser does not have significant variance in internal state that necessitates polymorphic behaviour for its public interface.