Bookstore classes design This is not homework. I am trying to learn OOD principles and design patterns myself.

Suppose I have a problem like this:


  A book-shop buys and sells two types of books:
  
  
  Non-technical {Title, Author, Price}
  Technical {Title, Author, Price, CD}
  
  
  Also, customer gets a CD when he buys a Technical book. A CD object is
  defined as, CD {Title, Price}.
  
  A Non-technical book's price will be only the price of the book. A
  Technical book's price will be the sum of the price of the book and
  the CD. 
  
  Create a C# program to show the following info:
  
  
  Total number of book Bought &amp; Price: XXX &amp; XXX.XX
  Total number of book Sold &amp; Price: XXX &amp; XXX.XX
  Total Technical Book Sold &amp; Price: XXX &amp; XXX.XX
  Total Non-technical Book sold &amp; Price: XXX &amp; XXX.XX
  


I have designed the program like this:

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&lt;string, Book&gt; boughtDictionary;
    private IDictionary&lt;string, Book&gt; soldDictionary;

    public Shop()
    {
        boughtDictionary = new Dictionary&lt;string, Book&gt;();
        soldDictionary = new Dictionary&lt;string, Book&gt;();
    }

    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 &amp; Price: ", this.GetTotalBookCount() + " &amp; " + this.GetTotalBookPrice());
        Console.WriteLine("Total number of books Sold &amp; Price: ", this.GetSoldBookCount() + " &amp; " + this.GetSoldBookPrice());
    }
}


Does this design conform to the Open-Closed principle? Now I am unable to understand how to separate Technical and Non-technical books at this point.
Overriding the Price property in TechnicalBook modifies the behavior of Publication. Which means you've broken the OCP. Besides, what do you expect TechnicalBook.Price to be if you have just set it to 10.0? (Does it even compile when you only override get?)

What you could do is employ the template method pattern:

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;
    }
}


This makes Publication closed for modification (cannot change price / individual price), but open for extension (can add to price).

(Naming and structure in my example could probably be improved, but it serves the purpose)

The behavior is still possible to modify, though, so an even better solution would be to have some collection or set of rules you can add to, so you don't accidentaly override GetAdditionalPrices without calling base.GetAdditionalPrices().