Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Лабораторная работа №3.
Объектная модель: проектирование структуры и реализация ключевых классов
Цели лабораторной работы:
Ход лабораторной работы:
Для оценки корректности выявления каждого конкретного класса следует дать ответы на следующие вопросы:
Идеальным случаем является наличие у каждого класса ровно 1 четкой обязанности.
Если обязанности сформулировать не получается, возможно существительное не является классом.
Если обязанностей несколько, возможно класс слишком большой и его следует разбить на несколько более мелких с 1 четкой обязанностью.
Наличие других классов, с которыми взаимодействует класс, свидетельствует о правильном выявлении, т.к. атрибуты связей с другими классами не имеют.
Если класс не взаимодействует ни с кем, маловероятно, что класс представляет собой объект-сущность. Отсутствие связей вполне допустимо для классов-значений.
На данном этапе можно остановиться, если устраивает оценка “удовлетворительно”. Для получения более высокой оценки следует выполнить остальные задания.
Заголовки классов следует размещать в отдельных заголовочных файлах, а реализации методов классов следует размещать в отдельных C++ файлах, имена которых должны соответствовать именам классов (например, класс Reservation объявление в reservation.hpp, реализация в reservation.cpp) ;
Пример простейшей объектной модели
Ниже приведена UML-диаграмма простейшей объектной модели, предназначенной для хранения данных о заказах товаров в магазине.
Созданные классы имеют следующие обязанности:
Ниже приведена упрощенная реализация данной модели на языке С++.
money.hpp
#ifndef _MONEY_HPP_
#define _MONEY_HPP_
//-----------------------------------------------------------------------------
#include <string>
//-----------------------------------------------------------------------------
class Money
{
//-------------------------
public:
//-------------------------
Money ();
Money ( unsigned int _integralPart, unsigned char _fractionalPart );
static Money fromString ( const std::string & _moneyAsText );
//-------------------------
std::string toString () const;
bool operator == ( const Money & _m ) const;
Money operator + ( Money const & _m ) const;
Money operator * ( unsigned int _n ) const;
//-------------------------
private:
//-------------------------
unsigned int m_integralPart;
unsigned char m_fractionalPart;
//-------------------------
};
//-----------------------------------------------------------------------------
#endif // _MONEY_HPP_
money.cpp
//-----------------------------------------------------------------------------
#include "money.hpp"
#include <boost/lexical_cast.hpp>
//-----------------------------------------------------------------------------
Money::Money ()
: m_integralPart( 0 ),
m_fractionalPart( 0 )
{
}
//-----------------------------------------------------------------------------
Money::Money ( unsigned int _integralPart, unsigned char _fractionalPart )
: m_integralPart( _integralPart ),
m_fractionalPart( _fractionalPart )
{
}
//-----------------------------------------------------------------------------
Money
Money::fromString ( const std::string & _moneyAsText )
{
double money = boost::lexical_cast< double >( _moneyAsText );
if ( money < 0. )
throw std::exception();
unsigned int integralPart = static_cast< unsigned int >( money );
unsigned char fractionalPart = static_cast< unsigned char >(
( money - integralPart ) * 100.0
);
return Money( integralPart, fractionalPart );
}
//-----------------------------------------------------------------------------
std::string
Money::toString () const
{
char buf[ 100 ];
sprintf( buf, "%d.%02d", m_integralPart, m_fractionalPart );
return buf;
}
//-----------------------------------------------------------------------------
bool
Money::operator == ( const Money & _m ) const
{
return m_integralPart == _m.m_integralPart &&
m_fractionalPart == _m.m_fractionalPart;
}
//-----------------------------------------------------------------------------
Money
Money::operator + ( Money const & _m ) const
{
unsigned int resultIngeralPart = m_integralPart + _m.m_integralPart;
unsigned char resultFractionalPart = m_fractionalPart + _m.m_fractionalPart;
if ( resultFractionalPart >= 100 )
{
++resultIngeralPart;
resultFractionalPart %= 100;
}
return Money( resultIngeralPart, resultFractionalPart );
}
//-----------------------------------------------------------------------------
Money
Money::operator * ( unsigned int _n ) const
{
unsigned int moneyInCents = m_integralPart * 100 + m_fractionalPart;
moneyInCents *= _n;
return Money( moneyInCents / 100, moneyInCents % 100 );
}
//-----------------------------------------------------------------------------
product.hpp
#ifndef _PRODUCT_HPP_
#define _PRODUCT_HPP_
//-----------------------------------------------------------------------------
#include "money.hpp"
#include <string>
//-----------------------------------------------------------------------------
class Product
{
//-------------------------
public:
//-------------------------
Product (
unsigned int _uniqueID,
const std::string & _name,
const std::string & _description,
const Money & _initialPrice
);
//-------------------------
unsigned int getUniqueID () const;
const std::string & getName () const;
const std::string & getDescription () const;
const Money & getCurrentPrice () const;
void setPrice ( const Money & _newPrice );
//-------------------------
private:
//-------------------------
const unsigned int m_uniqueID;
const std::string m_name;
const std::string m_description;
Money m_currentPrice;
//-------------------------
};
//-----------------------------------------------------------------------------
inline
unsigned int
Product::getUniqueID () const
{
return m_uniqueID;
}
//-----------------------------------------------------------------------------
inline
const std::string &
Product::getName () const
{
return m_name;
}
//-----------------------------------------------------------------------------
inline
const std::string &
Product::getDescription () const
{
return m_description;
}
//-----------------------------------------------------------------------------
inline
const Money &
Product::getCurrentPrice () const
{
return m_currentPrice;
}
//-----------------------------------------------------------------------------
inline
void
Product::setPrice ( const Money & _newPrice )
{
m_currentPrice = _newPrice;
}
//-----------------------------------------------------------------------------
#endif // _PRODUCT_HPP_
product.cpp
//-----------------------------------------------------------------------------
#include "product.hpp"
//-----------------------------------------------------------------------------
Product::Product (
unsigned int _uniqueID,
const std::string & _name,
const std::string & _description,
const Money & _initialPrice
)
: m_uniqueID( _uniqueID ),
m_name( _name ),
m_description( _description ),
m_currentPrice( _initialPrice )
{
}
//-----------------------------------------------------------------------------
item.hpp
#ifndef _ITEM_HPP_
#define _ITEM_HPP_
//-----------------------------------------------------------------------------
#include "money.hpp"
//-----------------------------------------------------------------------------
class Product;
//-----------------------------------------------------------------------------
class Item
{
//-------------------------
public:
//-------------------------
Item ( Product const & _product, unsigned int _quantity );
//-------------------------
Product const & getProduct () const;
unsigned int getQuantity () const;
void setQuantity ( unsigned int _newQuantity );
Money getPrice () const;
Money getCost () const;
//-------------------------
private:
//-------------------------
Product const & m_product;
unsigned int m_quantity;
Money const m_price;
//-------------------------
};
//-----------------------------------------------------------------------------
inline
Product const &
Item::getProduct () const
{
return m_product;
}
//-----------------------------------------------------------------------------
inline
unsigned int
Item::getQuantity () const
{
return m_quantity;
}
//-----------------------------------------------------------------------------
inline
void
Item::setQuantity ( unsigned int _newQuantity )
{
m_quantity = _newQuantity;
}
//-----------------------------------------------------------------------------
inline
Money
Item::getPrice () const
{
return m_price;
}
//-----------------------------------------------------------------------------
#endif // _ITEM_HPP_
item.cpp
//-----------------------------------------------------------------------------
#include "item.hpp"
#include "product.hpp"
//-----------------------------------------------------------------------------
Item::Item ( Product const & _product, unsigned int _quantity )
: m_product( _product ),
m_price( _product.getCurrentPrice() ),
m_quantity ( _quantity )
{
}
//-----------------------------------------------------------------------------
Money
Item::getCost () const
{
return m_price * m_quantity;
}
//-----------------------------------------------------------------------------
order.hpp
#ifndef _ORDER_HPP_
#define _ORDER_HPP_
//-----------------------------------------------------------------------------
#include "money.hpp"
#include <vector>
//-----------------------------------------------------------------------------
class Item;
class Product;
//-----------------------------------------------------------------------------
class Order
{
//-------------------------
public:
//-------------------------
Order ( unsigned int _uniqueID, time_t _registeredAt );
~Order ();
//-------------------------
unsigned int getUniqueID () const;
time_t getRegistrationTime () const;
//-------------------------
unsigned int getItemsCount () const;
Item const & getItem ( unsigned int _itemIndex ) const;
Item & newItem ( Product const & _item, unsigned int _quantity );
void removeItem ( Item & _item );
//-------------------------
Money getCost () const;
//-------------------------
private:
//-------------------------
const unsigned int m_uniqueID;
const time_t m_registeredAt;
typedef std::vector< Item * > Items;
Items m_items;
//-------------------------
};
//-----------------------------------------------------------------------------
inline
unsigned int
Order::getUniqueID () const
{
return m_uniqueID;
}
//-----------------------------------------------------------------------------
inline
time_t
Order::getRegistrationTime () const
{
return m_registeredAt;
}
//-----------------------------------------------------------------------------
inline
unsigned int
Order::getItemsCount () const
{
return m_items.size();
}
//-----------------------------------------------------------------------------
inline
Item const &
Order::getItem ( unsigned int _itemIndex ) const
{
return * ( m_items.at( _itemIndex ) );
}
//-----------------------------------------------------------------------------
#endif // _ORDER_HPP_
order.cpp
//-----------------------------------------------------------------------------
#include "order.hpp"
#include "item.hpp"
#include <algorithm>
#include <boost/checked_delete.hpp>
#include <exception>
//-----------------------------------------------------------------------------
Order::Order ( unsigned int _uniqueID, time_t _registeredAt )
: m_uniqueID( _uniqueID ),
m_registeredAt( _registeredAt )
{
}
//-----------------------------------------------------------------------------
Order::~Order ()
{
std::for_each(
m_items.begin(),
m_items.end(),
boost::checked_deleter< Item >()
);
}
//-----------------------------------------------------------------------------
Item &
Order::newItem ( Product const & _product, unsigned int _quantity )
{
Item * pNewItem = new Item( _product, _quantity );
m_items.push_back( pNewItem );
return * pNewItem;
}
//-----------------------------------------------------------------------------
void
Order::removeItem ( Item & _item )
{
Items::iterator it = std::find( m_items.begin(), m_items.end(), & _item );
if ( it == m_items.end() )
throw std::exception();
m_items.erase( it );
}
//-----------------------------------------------------------------------------
Money
Order::getCost () const
{
Money totalCost = Money();
Items::const_iterator it = m_items.begin();
while ( it != m_items.end() )
{
const Item * pItem = * it;
totalCost = totalCost + pItem->getCost();
++ it;
}
return totalCost;
}
//-----------------------------------------------------------------------------
shop.hpp
#ifndef _SHOP_HPP_
#define _SHOP_HPP_
//-----------------------------------------------------------------------------
#include <string>
#include <vector>
#include <map>
#include <memory>
//-----------------------------------------------------------------------------
class Product;
class Order;
class Money;
//-----------------------------------------------------------------------------
class Shop
{
//-------------------------
public:
//-------------------------
Shop ( const std::string &_title );
~Shop ();
//-------------------------
const std::string & getTitle () const;
//-------------------------
Product const & addProduct (
const std::string & _productName,
const std::string & _description,
const Money & _initialPrice
);
void dropProduct ( const std::string & _name );
unsigned int getProductsCount () const;
Product const * findProduct ( const std::string & _name ) const;
class ProductIterator
{
public:
virtual bool hasNext () const = 0;
virtual Product const & getProduct () const = 0;
virtual void next () = 0;
};
std::auto_ptr< ProductIterator > browseProducts () const;
//-------------------------
unsigned int getOrdersCount () const;
const Order & getOrder ( unsigned int _orderIndex ) const;
Order & newOrder ();
//-------------------------
private:
//-------------------------
const std::string m_title;
typedef std::map< std::string, Product * > ProductDescriptions;
ProductDescriptions m_products;
std::vector< Order * > m_orders;
//-------------------------
};
//-----------------------------------------------------------------------------
inline
const std::string &
Shop::getTitle () const
{
return m_title;
}
//-----------------------------------------------------------------------------
inline
unsigned int
Shop::getProductsCount () const
{
return m_products.size();
}
//-----------------------------------------------------------------------------
inline
unsigned int
Shop::getOrdersCount () const
{
return m_orders.size();
}
//-----------------------------------------------------------------------------
inline
const Order &
Shop::getOrder ( unsigned int _orderIndex ) const
{
return *( m_orders.at( _orderIndex ) );
}
//-----------------------------------------------------------------------------
#endif // _SHOP_HPP_
shop.cpp
//-----------------------------------------------------------------------------
#include "shop.hpp"
#include "order.hpp"
#include "product.hpp"
#include <ctime>
#include <algorithm>
#include <exception>
#include <boost/checked_delete.hpp>
//-----------------------------------------------------------------------------
Shop::Shop ( const std::string & _title )
: m_title( _title )
{
}
//-----------------------------------------------------------------------------
Shop::~Shop ()
{
std::for_each(
m_orders.begin(),
m_orders.end(),
boost::checked_deleter< Order >()
);
std::for_each(
m_products.begin(),
m_products.end(),
std::compose1(
boost::checked_deleter< Product >(),
std::select2nd< ProductDescriptions::value_type >()
)
);
}
//-----------------------------------------------------------------------------
Order &
Shop::newOrder ()
{
Order * pNewOrder = new Order( getOrdersCount(), time( NULL ) );
m_orders.push_back( pNewOrder );
return * pNewOrder;
}
//-----------------------------------------------------------------------------
Product const &
Shop::addProduct (
const std::string & _productName,
const std::string & _description,
const Money & _initialPrice
)
{
if ( findProduct( _productName ) )
throw std::exception();
Product * pProduct = new Product(
m_products.size(), /* id */
_productName,
_description,
_initialPrice
);
m_products.insert(
std::make_pair(
pProduct->getName(),
pProduct
)
);
return * pProduct;
}
//-----------------------------------------------------------------------------
void
Shop::dropProduct ( const std::string & _name )
{
ProductDescriptions::iterator it = m_products.find( _name );
if ( it != m_products.end() )
{
Product * pProduct = it->second;
m_products.erase( it );
delete pProduct;
}
else
throw std::exception();
}
//-----------------------------------------------------------------------------
Product const *
Shop::findProduct ( const std::string & _name ) const
{
ProductDescriptions::const_iterator it = m_products.find( _name );
if ( it == m_products.end() )
return NULL;
return it->second;
}
//-----------------------------------------------------------------------------
std::auto_ptr< Shop::ProductIterator >
Shop::browseProducts () const
{
class ProductIteratorImpl
: public ProductIterator
{
//-----------------------
public:
//-----------------------
ProductIteratorImpl ( ProductDescriptions const & _descriptions )
: m_descriptions( _descriptions ),
m_it( _descriptions.begin() )
{
}
//-----------------------
virtual bool hasNext () const
{
return m_it != m_descriptions.end();
}
//-----------------------
virtual Product const & getProduct () const
{
return *( m_it->second );
}
//-----------------------
virtual void next ()
{
++ m_it;
}
//-----------------------
private:
//-----------------------
ProductDescriptions const & m_descriptions;
ProductDescriptions::const_iterator m_it;
//-----------------------
};
return std::auto_ptr< ProductIterator >(
new ProductIteratorImpl( m_products )
);
}
//-----------------------------------------------------------------------------
Пример тестовой программы
Использование рассмотренной выше упрошенной объектной модели магазина может быть продемонстрировано при помощи тестовой программы, которая:
test.cpp
//-----------------------------------------------------------------------------
#include "shop.hpp"
#include "order.hpp"
#include "item.hpp"
#include "product.hpp"
#include "money.hpp"
#include <cassert>
#include <cstdio>
//-----------------------------------------------------------------------------
void showShopStats ( const Shop & _shop )
{
printf( "Shop \"%s\" has %d products:\n",
_shop.getTitle().c_str(),
_shop.getProductsCount()
);
std::auto_ptr< Shop::ProductIterator > productIt = _shop.browseProducts();
while ( productIt->hasNext() )
{
Product const & product = productIt->getProduct();
printf( " - [%d] \"%s\", desription: \"%s\", price: %s\n",
product.getUniqueID(),
product.getName().c_str(),
product.getDescription().c_str(),
product.getCurrentPrice().toString().c_str()
);
productIt->next();
}
putchar( '\n' );
unsigned int nOrders = _shop.getOrdersCount();
printf( "Totally there were %d order(s) registered\n", nOrders );
putchar( '\n' );
for ( unsigned int i = 0; i < nOrders; i++ )
{
const Order & order = _shop.getOrder( i );
printf( "Order %d contains %d items with total cost of %s:\n",
order.getUniqueID(),
order.getItemsCount(),
order.getCost().toString().c_str()
);
unsigned int nItems = order.getItemsCount();
for ( unsigned int k = 0; k < nItems; k++ )
{
const Item & item = order.getItem( k );
printf( " Product = '%s', Quantity = %d, Price = %s, Cost = %s\n",
item.getProduct().getName().c_str(),
item.getQuantity(),
item.getPrice().toString().c_str(),
item.getCost().toString().c_str() );
}
putchar( '\n' );
}
putchar( '\n' );
}
//-----------------------------------------------------------------------------
void main ()
{
/////
const char * SHOP_TITLE = "MyShop";
Shop shop( SHOP_TITLE );
/////
assert( shop.getTitle() == SHOP_TITLE );
assert( shop.getOrdersCount() == 0 );
assert( shop.getProductsCount() == 0 );
/////
Product const & batteries = shop.addProduct(
"Batteries",
"A pack with 4 batteries",
Money::fromString( "12.00" )
);
Product const & dvdDisk = shop.addProduct(
"DVD disk",
"A blank DVD disk for recording",
Money::fromString( "3.00" )
);
/////
assert( shop.getProductsCount() == 2 );
assert( shop.findProduct( "Batteries" ) == & batteries );
assert( shop.findProduct( "DVD disk" ) == & dvdDisk );
assert( shop.findProduct( "other-product" ) == NULL );
/////
Order & order = shop.newOrder();
order.newItem( batteries, 1 );
order.newItem( dvdDisk, 3 );
/////
assert( order.getCost().toString() == "21.00" );
assert( order.getItemsCount() == 2 );
assert( order.getItem( 0 ).getQuantity() == 1 );
assert( order.getItem( 0 ).getCost() == batteries.getCurrentPrice() );
assert( order.getItem( 1 ).getQuantity() == 3 );
assert( order.getItem( 1 ).getCost() == ( dvdDisk.getCurrentPrice() * 3 ) );
/////
showShopStats( shop );
}
//-----------------------------------------------------------------------------
Процедура защиты лабораторной работы: