这不是作业。我正在努力学习OOD原则和设计模式自己。
假设我有这样的问题:
书店买卖两种类型的书:
此外,客户购买一本技术书籍时会得到一张CD。CD对象定义为,CD {Title,Price}。非技术书籍的价格将仅为书的价格.技术书的价格是书和CD的价格之和。创建一个C#程序以显示以下信息:
我设计了这样的程序:
abstract class Publication
{
public virtual string Title { get; set; }
public virtual double Price { get; set; }
}
class CD : Publication
{
}
abstract class Book : Publication
{
public virtual string Author { get; set; }
}
class TechnicalBook : Book
{
public CD Cd { get; set; }
public override double Price
{
get
{
return (base.Price + Cd.Price);
}
}
}
class NonTechnicalbook : Book
{
}
abstract class Shop
{
private IDictionary<string, Book> boughtDictionary;
private IDictionary<string, Book> soldDictionary;
public Shop()
{
boughtDictionary = new Dictionary<string, Book>();
soldDictionary = new Dictionary<string, Book>();
}
public virtual void Buy(Book item)
{
boughtDictionary.Add(item.Title, item);
}
public virtual void Sell(string title)
{
Book book = boughtDictionary[title];
boughtDictionary.Remove(book.Title);
soldDictionary.Add(book.Title, book);
}
public virtual int GetBoughtBookCount()
{
return boughtDictionary.Count;
}
public virtual double GetBoughtBookPrice()
{
double price = 0.0;
foreach (string title in boughtDictionary.Keys)
{
price = price + boughtDictionary[title].Price;
}
}
public virtual int GetSoldBookCount()
{
return boughtDictionary.Count;
}
public virtual double GetSoldBookPrice()
{
double price = 0.0;
foreach (string title in soldDictionary.Keys)
{
price = price + soldDictionary[title].Price;
}
}
public virtual double GetTotalBookCount()
{
return this.GetBoughtBookCount() + this.GetSoldBookCount();
}
public virtual double GetTotalBookPrice()
{
return this.GetBoughtBookPrice() + this.GetSoldBookPrice();
}
public virtual void Show()
{
Console.WriteLine("Total number of books Bought & Price: ", this.GetTotalBookCount() + " & " + this.GetTotalBookPrice());
Console.WriteLine("Total number of books Sold & Price: ", this.GetSoldBookCount() + " & " + this.GetSoldBookPrice());
}
}这种设计是否符合开闭原则?现在我无法理解如何将技术书和非技术书分开。
发布于 2012-02-09 10:39:14
在Price中重写TechnicalBook属性会修改Publication的行为。这意味着你破坏了OCP。此外,如果您刚刚将TechnicalBook.Price设置为10.0,您希望它是什么?(当您只覆盖get时,它会编译吗?)
您可以做的是使用模板方法模式:
abstract class Publication
{
// ...
public decimal IndividualPrice { get; set; }
public decimal Price {
get { return CalculatePrice(); }
}
protected decimal CalculatePrice() {
decimal price = IndividualPrice;
price += GetAdditionalPrices();
return price;
}
protected virtual decimal GetAdditionalPrices() {
return 0;
}
}
public class TechnicalBook : Publication
{
// ...
protected override decimal GetAdditionalPrices() {
return Cd.Price;
}
}这使得Publication因修改而关闭(不能更改价格/单个价格),但对扩展开放(可以增加价格)。
(我的示例中的命名和结构可能会得到改进,但它可以达到目的)
不过,这种行为仍然可以修改,因此更好的解决方案是可以添加一些集合或规则集,这样就不会在不调用GetAdditionalPrices的情况下意外地覆盖base.GetAdditionalPrices()。
发布于 2012-02-09 10:16:46
我不谈公开-封闭原则,因为我不知道。
中分离技术
第二个问题属于StackOverflow。
还有一个理由为你的每一个真正的问题打开一个单独的问题..。
但你可以这样做:
if(book is TechnicalBook) {
// ...
} else if(book is NonTechnicalBook) {
// ...
} else {
// This is why I would suggest Book class not being abstract...
// and removing the NonTechnicalBook class, making the TechnicalBook extend Book.
throw new ArgumentException();
}的注释
public CD Cd应该是Cd Cd或CD CD。NonTechnicalbook的定义有什么好处。如果不是抽象的,你就不能用普通的书吗?,但也许这是您提到的原则的一部分。IDictionary<string, Book> boughtDictionary;,如果我买两本名为C# for Dummies的书呢?这应该是一个Dictionary<Book, int>。dictionary是匈牙利符号 --这是我要避免的。你试过运行你的代码吗?例如:-您的Console.WriteLine()不像您期望的那样工作,您有一个逗号而不是一个加号;-有些方法甚至不返回值,因此不编译;- GetSoldBookCount正在使用boughtDictionary;-等等。
闻起来很像家庭作业。
这感觉真像家庭作业。
(对括号缩进表示抱歉。太麻烦了,不能把它改回你的风格。)
namespace BookSellers
{
using System.Linq;
abstract class Publication
{
public virtual string Title { get; set; }
public virtual double Price { get; set; }
}
class CD : Publication
{
}
abstract class Book : Publication
{
public virtual string Author { get; set; }
}
class TechnicalBook : Book
{
public CD CD { get; set; }
public override double Price {
get {
return (base.Price + CD.Price);
}
}
}
class NonTechnicalbook : Book
{
}
abstract class Shop
{
private IDictionary<Book, int> BooksInStock;
private IDictionary<Book, int> BooksSold;
public Shop() {
BooksInStock = new Dictionary<Book, int>();
BooksSold = new Dictionary<Book, int>();
}
public virtual void Buy(Book book) {
int count;
if (!BooksInStock.TryGetValue(book, out count)) {
count = 0;
}
BooksInStock[book] = count + 1;
}
public virtual void Sell(Book book) {
int count;
if (!BooksInStock.TryGetValue(book, out count)
|| count < 1
) {
throw new ArgumentException("Book is not in stock.", "book");
}
BooksInStock[book] = count - 1;
if (!BooksSold.TryGetValue(book, out count)) {
count = 0;
}
BooksSold[book] = count + 1;
}
public virtual int GetTotalBooksCount() {
return GetStockCount() + GetSoldBooksCount();
}
public virtual int GetStockCount() {
return BooksInStock.Values.Sum();
}
public virtual int GetSoldBooksCount() {
return BooksSold.Values.Sum();
}
public virtual double GetTotalBooksPrice() {
return GetStockBooksPrice() + GetSoldBooksPrice();
}
public virtual double GetStockBooksPrice() {
return BooksInStock.Sum(pair => pair.Key.Price * pair.Value);
/* Same as:
double price = 0.0;
foreach (var pair in BooksInStock) {
Book book = pair.Key;
int count = pair.Value;
price += book.Price * count;
}
return price;*/
}
public virtual double GetSoldBooksPrice() {
return BooksSold.Sum(pair => pair.Key.Price * pair.Value);
}
public virtual void Show() {
Console.WriteLine(string.Format(
"Total number of books Bought & Price: {0} & {1}",
GetTotalBooksCount(),
GetTotalBooksPrice()
));
Console.WriteLine(string.Format(
"Total number of books Sold & Price: {0} & {1}",
GetSoldBooksCount(),
GetSoldBooksPrice()
));
}
}
}https://codereview.stackexchange.com/questions/8797
复制相似问题