这就是我想出的。
任何想法:
public enum CoffeeKind
{
Black = 1,
Cappuccino,
Espresso
}
public class Coffee
{
//Measured in celcius
public int Temprature { get; set; } = 30;
public bool HasMilk { get; set; }
public int Sugar { get; set; }
public CoffeeKind Kind { get; set; }
public bool Cold => Temprature < 24;
}
public enum CupSize
{
Small = 1,
Medium,
Large,
ExtraLarge
}
public class Cup
{
public static Cup SMALL = new Cup(CupSize.Small);
public static Cup MEDIUM = new Cup(CupSize.Medium);
public static Cup LARGE = new Cup(CupSize.Large);
public static Cup EXTRA_LARGE = new Cup(CupSize.ExtraLarge);
public static Dictionary<CupSize, Cup> Cups = new Dictionary<CupSize, Cup>
{
[CupSize.Small] = SMALL,
[CupSize.Medium] = MEDIUM,
[CupSize.Large] = LARGE,
[CupSize.ExtraLarge] = EXTRA_LARGE
};
public CupSize Size { get; }
public int Amount { get; set; }
public bool Empty => Amount == 0;
public Coffee Coffee { get; set; }
private Cup() : this(CupSize.Medium) { }
private Cup(CupSize size)
{
Size = size;
}
public void Fill(CoffeeKind kind)
{
if (Empty)
{
Coffee = new Coffee { Kind = kind };
Amount = SetAmountBySize(Size);
}
}
private static int SetAmountBySize(CupSize size)
{
switch (size)
{
case CupSize.Small:
return 100;
case CupSize.Large:
return 300;
case CupSize.ExtraLarge:
return 400;
case CupSize.Medium:
default:
return 200;
}
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Name => $"{FirstName} {LastName}";
public Cup Cup { get; set; }
public Person() { }
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public void GetCoffee(CupSize size, CoffeeKind kind)
{
Cup = Cup.Cups[size];
Cup.Fill(kind);
}
public void Drink()
{
if (Cup?.Empty == false && Cup?.Coffee?.Cold == false)
{
Cup.Amount = 0;
}
}
public void Drink(int amount)
{
if (Cup?.Empty == false && Cup?.Coffee?.Cold == false)
{
Cup.Amount -= amount;
}
}
}
class Program
{
const int EXIT = -1;
const int GET_COFFEE = 1;
const int DRINK_COFFEE = 2;
const int DRINK_AMOUNT = 3;
//TODO change these to use values of enum - or just change the calls to them
const int SMALL = 1;
const int MEDIUM = 2;
const int LARGE = 3;
const int EXTRA_LARGE = 4;
const int BLACK = 1;
const int CAPPUCCINO = 2;
const int ESPRESSO = 3;
static Person person;
static void Main(string[] args)
{
Console.WriteLine("Enter first name:");
string firstName = Console.ReadLine();
Console.WriteLine("Enter last name:");
string lastName = Console.ReadLine();
person = new Person(firstName, lastName);
var choice = GetUserAction();
while (choice != EXIT)
{
if (choice == GET_COFFEE)
{
if (person?.Cup?.Empty == false)
{
Console.WriteLine("Old coffee will be thrown out");
}
int cupSize = GetCupSize();
int coffeeKind = GetCoffeKind();
person.GetCoffee((CupSize)cupSize, (CoffeeKind)coffeeKind);
Console.WriteLine($"Got a {person.Cup.Size.ToString()} size {person.Cup.Coffee.Kind.ToString()} coffee");
}
else if (choice == DRINK_COFFEE)
{
if (person?.Cup?.Empty == false)
{
person.Drink();
}
else
{
Console.WriteLine("Can not drink without coffee!");
}
}
choice = GetUserAction();
}
}
private static int GetCoffeKind()
{
Console.WriteLine($"{BLACK}: Black");
Console.WriteLine($"{CAPPUCCINO}: Cappuccino");
Console.WriteLine($"{ESPRESSO}: Espresso");
var result = int.Parse(Console.ReadLine());
if (result < BLACK || result > ESPRESSO)
{
return GetCoffeKind();
}
return result;
}
private static int GetCupSize()
{
Console.WriteLine($"{SMALL}: {nameof(SMALL)}");
Console.WriteLine($"{MEDIUM}: Medium");
Console.WriteLine($"{LARGE}: Large");
Console.WriteLine($"{EXTRA_LARGE}: Extra Large");
var result = int.Parse(Console.ReadLine());
if (result < SMALL || result > EXTRA_LARGE)
{
return GetCupSize();
}
return result;
}
private static int GetUserAction()
{
Console.WriteLine("What would you like to do:");
Console.WriteLine($"{GET_COFFEE}: Get coffee");
// You can't drink coffee without a cup
if (person?.Cup != null)
{
Console.WriteLine($"{DRINK_COFFEE}: Drink coffee");
Console.WriteLine($"{DRINK_AMOUNT}: Drink some coffee");
}
Console.WriteLine($"{EXIT}: Exit");
return int.Parse(Console.ReadLine());
}
}
#1 楼
您正在滥用null传播运算符。例如person = new Person(firstName, lastName);
var choice = GetUserAction();
while (choice != EXIT)
{
if (choice == GET_COFFEE)
{
if (person?.Cup?.Empty == false)
{
人不可能成为
null
。创建之后,您再也不会将其设置为其他任何东西。有趣的是,我认为这将是C#6的最常用功能,但我几乎从不使用它。您的常数应该是SHOUT_CASE
。如果您要为一个枚举成员设置一个显式值,那么我想您应该对它们全部进行以下操作:
public enum CoffeeKind
{
Black = 1,
Cappuccino = 2,
Espresso = 3
}
我认为您的模型在这里有点过时了。浓缩咖啡是黑咖啡,即其中没有牛奶。
public enum DrinkType
{
FilterCoffee,
Cappuccino,
Espresso
}
我认为通常这不是一个枚举。如果我想喝一杯咖啡,该怎么办?我认为您需要可以组成的饮料课。
我在这些领域没有意义:
/>您已经有一个枚举-确保正确实施了平等性,并让人们创建自己的保温杯。
如上所述:
public static Cup SMALL = new Cup(CupSize.Small);
public static Cup MEDIUM = new Cup(CupSize.Medium);
public static Cup LARGE = new Cup(CupSize.Large);
public static Cup EXTRA_LARGE = new Cup(CupSize.ExtraLarge);
如果您想了解杯具,您需要一个橱柜: />
public static Dictionary<CupSize, Cup> Cups = new Dictionary<CupSize, Cup>
{
[CupSize.Small] = SMALL,
[CupSize.Medium] = MEDIUM,
[CupSize.Large] = LARGE,
[CupSize.ExtraLarge] = EXTRA_LARGE
};
这是一种奇怪的方法:空吗
如果将“数量”设置为0到0,没人会注意到
我经常分心并尝试从空杯子里喝酒(有时甚至是昨天的杯子)
如果未执行该操作,则应该
PascalCase
。或者,如果您认为自己的人(像我一样)将致力于喝杯中的任何东西,那么就应该始终让他们这样做。是TryDrink
。评论
\ $ \ begingroup \ $
“你喜欢冷咖啡”,哈哈。好答案!
\ $ \ endgroup \ $
–方言
16-2-2在17:51
\ $ \ begingroup \ $
@Max-一个IRepository可能有点多,但我认为知道可用的杯子尺寸不是杯子的责任。我会说60°C的咖啡温度得到了这项研究的支持,我无法相信这是真实的。
\ $ \ endgroup \ $
– RobH
16年3月3日在8:36
\ $ \ begingroup \ $
codereview.stackexchange.com/questions/118647/…-我可能会降低温度。杯子应该知道它是什么尺寸,对吗?那么也许带有名称和金额的CupSize结构?
\ $ \ endgroup \ $
–祖伯勋爵
16年3月3日在8:47
\ $ \ begingroup \ $
@Max-我想说一个杯子应该知道它的容量,您可以将其编码为一组预定义的大小,不可变结构的集合听起来像是一个不错的选择。
\ $ \ endgroup \ $
– RobH
16年3月3日,9:37
\ $ \ begingroup \ $
@IsmaelMiguel选择温度的方法太过等待v2;)mug == cup(基于JavaScript相等性)。根据罗马规约,用橡皮鸭喝咖啡是非法的
\ $ \ endgroup \ $
–祖伯勋爵
16年3月3日在13:18
#2 楼
快速说明int GetCupSize()
,int GetUserAction()
和int GetCoffeKind()
使用
int.TryParse()
会更好,因此任何无效的输入字符都不会引发异常。int SetAmountBySize(CupSize size)
您实际上并没有在此处设置金额。尝试找到一个更好的名称。
常规
而不是
if (someBoolean == false)
,应使用更惯用的方式,例如if (!someBoolean)
。评论
\ $ \ begingroup \ $
SetAmountBySize很好。将前缀从set更改为get。 booleanVar == false是因为我正在使用Elvis运算符,所以它可以为空
\ $ \ endgroup \ $
–祖伯勋爵
16-2-2在15:47
\ $ \ begingroup \ $
你会说!(bool)person?.Cup?.Empty比person?.Cup?.Empty == false吗?如果可以,为什么?
\ $ \ endgroup \ $
–祖伯勋爵
16年2月2日在15:55
\ $ \ begingroup \ $
不,不是真的;-)但是人不会为空(主要是)
\ $ \ endgroup \ $
– Heslacher
16-2-2在15:59
\ $ \ begingroup \ $
感谢您的反馈,我已经修复了所有空检查。
\ $ \ endgroup \ $
–祖伯勋爵
16年2月2日在20:19
#3 楼
我会说杯子里的代码逻辑存在缺陷:)。应该更像以下内容:Cup coffeeCup = new Cup(size);
while(true)
{
if(cup.IsEmpty)
{
cup.Refill(coffeeType);
}
cup.Drink();
}
话虽如此,关于您的代码,我只删除了以下几行:
public static Cup SMALL = new Cup(CupSize.Small);
public static Cup MEDIUM = new Cup(CupSize.Medium);
public static Cup LARGE = new Cup(CupSize.Large);
public static Cup EXTRA_LARGE = new Cup(CupSize.ExtraLarge);
,因为它们并没有增加与IMO相关的任何内容。
评论
\ $ \ begingroup \ $
话虽如此,关于您的代码,我只需要删除以下几行:这些只是方便的方法,可以快速获得如此大小的预制杯子
\ $ \ endgroup \ $
–祖伯勋爵
16年2月2日在20:20
\ $ \ begingroup \ $
@Max是的,我的意思是,它并没有增加太多相关性。我更喜欢使用新的Cup(size)指令或某些工厂方法,例如MakeCup(size)或MakeSmallCup()(或MakeMediumCup()等)。
\ $ \ endgroup \ $
–龙胆K
16年3月3日在7:19
\ $ \ begingroup \ $
感谢您的反馈。我将围绕获得的所有反馈进行讨论,并发布后续帖子(问题)
\ $ \ endgroup \ $
–祖伯勋爵
16-2-3在7:22
#4 楼
我的评论:OO-这是洒了的杯子。到处都是。除了CupofCoffee,您已经拥有所有东西。标题中的“分配器”只能通过泄漏来推断。
最大:
@radarbob您想详细说明吗?
/>
static void Main(string[] args){
Person theDeveloper = new Person();
Dispenser coffeeMaker = new Dispenser();
CoffeeOrder whatIWant = GetUserAction();
CupOfCoffee myCuppa = CoffeeMaker.Brew(whatIWant);
theDeveloper.Drink(myCuppa);
}
面向对象的枚举
结构
封装
控制反转
对域建模。每个OP都有一个分配器和一个咖啡杯。
单一责任原则-是的,它适用于方法。
编写此代码时不会损害任何属性。
艾伦·凯(Alan Kay)解释说:“如果直接设置状态而不使用方法,那是错的。”
OO是分形的-不要仅仅因为以下原因而放弃应用设计:
“代码不多”
”方法很小,我们可以在此处添加更多代码”
看!一类。那是OO!太好了!让代码栏开始。
现实,已中断:
//TODO change these...
我们的生产代码库中有700多个。代码就像释放时的快干水泥。 很快就被扔到了一起
就到那儿了。而且我个人认为,这体现为在正式测试中花费2天和3个月的地狱测试失败修复周期之间的差异。 >
评论
\ $ \ begingroup \ $
谢谢。在我当前的代码库中,程序是分配器。但是您的榜样无疑启发了我。我可能只是创建一个单独的项目,以免被我已经写的东西所困扰
\ $ \ endgroup \ $
–祖伯勋爵
16年3月3日在15:49
\ $ \ begingroup \ $
“ OO是分形的-不要仅仅因为以下原因而放弃应用设计”。这只是一次快速的尝试。我收到的所有反馈将帮助我更好地重写它。
\ $ \ endgroup \ $
–祖伯勋爵
16年3月3日在15:51
\ $ \ begingroup \ $
我从问这个愚蠢的小玩具程序中学到了更多有关OO的知识,而不是从我以前尝试过的任何讲座/书中得到的:)
\ $ \ endgroup \ $
–祖伯勋爵
16年3月3日在16:14
评论
评论不作进一步讨论;此对话已移至聊天。在编写此代码时,请确保实现与此处记录的正确的和一致的协议支持相关标准兼容。
令人失望的是,您选择使用C#而不是Java编写此代码。我的意思是,我通常更喜欢C#,但是您应该为该工作选择最合适的工具