Problem z designem

0

Proszę o ocenę designu poniższych klas:

 
class Frame_pool {
public:
	virtual ~Frame_pool()
	{

	}
};

class Video_frame_pool : public Frame_pool {
public:
	int pixel_format;

	int get_pixel_format()
	{
		return pixel_format;
	}
};

class Audio_frame_pool : public Frame_pool {
public:
	int bit_depth;

	int get_bit_depth()
	{
		return bit_depth;
	}
};



class Frame {
public:
	Frame_pool *pool;
};

class Video_frame : public Frame {
public:
	int get_pixel_format()
	{
		Video_frame_pool *v_pool = dynamic_cast<Video_frame_pool *>(pool);
		return v_pool->get_pixel_format();
	}
};

class Audio_frame : public Frame {
public:
	int get_bit_depth()
	{
		Audio_frame_pool *a_pool = dynamic_cast<Audio_frame_pool *>(pool);
		return a_pool->get_bit_depth();
	}
};

Założenia designu są następujące:

  • wszystkie ramki z danej puli przechowują dane o tych samych parametrach, stąd pola takie jak pixel_format umieściłem w klasie Video_pool, a nie Video_frame.
  • obiekty korzystające z ramek nie posiadają bezpośredniej referencji do obiektu puli, stąd obiekt ramki posiada metodę do zwracania poszczególnych parametrów.
  • widoczność poszczególnych pól jest przykładowa - dla uproszczenia ustawiłem wszystko na public.

Jedyne co mi się nie podoba w powyższym designie to konieczność wywoływania dynamic_cast. Chciałbym tego uniknąć, bo brzydko to wygląda tylko nie bardzo wiem jak zmienić design, aby się tego pozbyć i jednocześnie zachować wyżej wymienione założenia. Stąd też proszę o pomoc.

0

Moim zdaniem to dziedziczenie z frame do Video_frame i frame do Audio_frame jest zbyteczne. W środku w metodach od tych klas robisz rzutowanie w dół tylko po to aby wywołać odpowiednie metody obiektów klas Audio_frame_pool i Video_frame_pool(czyli tak jakby poszerzasz interfejs). Ten wskaźnik: Frame_pool *pool jest też zbyteczny. Bo niby co chcesz przez to osiągnąć. Klasa nadrzędna Frame_pool nie posiada żadnych metod interfejsu. Więć siłą żeczą nie damy rady manipulować obiektami klas pochodnych, ponieważ poszerzają one interfejs(metody int get_pixel_format() i int get_bit_depth()). Zatem to co ty zrobiłeś jest zupełnie bez sensu. Zatem w tym przypadku jeśli chcesz użyć tego kodu musisz wywalić ten fragment:

 
class Frame {
public:
        Frame_pool *pool;
};
 
class Video_frame : public Frame {
public:
        int get_pixel_format()
        {
                Video_frame_pool *v_pool = dynamic_cast<Video_frame_pool *>(pool);
                return v_pool->get_pixel_format();
        }
};
 
class Audio_frame : public Frame {
public:
        int get_bit_depth()
        {
                Audio_frame_pool *a_pool = dynamic_cast<Audio_frame_pool *>(pool);
                return a_pool->get_bit_depth();
        }
};

Stwórz sobie obiekty typu Video_frame_pool i Audio_frame_pool i zwyczajnie odwołuj się do metod. A nie komplikuj sobie życia.

0

Problem polega na tym, że klasy Frame czy Frame_pool też w zamierzeniu mają posiadać elementy interfejsu wspólne dla obu dziedziczących klas. Moim błędem było, że nie zamieściłem żadnego takiego interfejsu w przykładzie, stąd faktycznie użyty design mógł wydać się zupełnie nieadekwatny. Poniżej zamieszczam więc uzupełnioną wersję kodu:

class Frame_pool {
public:
	int max_frame_size;

	int get_max_frame_size()
	{
		return max_frame_size;
	}

        virtual ~Frame_pool()
        {
 
        }
};
 
class Video_frame_pool : public Frame_pool {
public:
        int pixel_format;
 
        int get_pixel_format()
        {
                return pixel_format;
        }
};
 
class Audio_frame_pool : public Frame_pool {
public:
        int bit_depth;
 
        int get_bit_depth()
        {
                return bit_depth;
        }
};
 
 
 
class Frame {
public:
        Frame_pool *pool;
};
 
class Video_frame : public Frame {
public:
	int get_max_frame_size()
	{
		return pool->get_max_frame_size();
	}

        int get_pixel_format()
        {
                Video_frame_pool *v_pool = dynamic_cast<Video_frame_pool *>(pool);
                return v_pool->get_pixel_format();
        }
};
 
class Audio_frame : public Frame {
public:
	int get_max_frame_size()
	{
		return pool->get_max_frame_size();
	}

        int get_bit_depth()
        {
                Audio_frame_pool *a_pool = dynamic_cast<Audio_frame_pool *>(pool);
                return a_pool->get_bit_depth();
        }
};

Teraz chyba widać, że taki design ma większy sens.

1 użytkowników online, w tym zalogowanych: 0, gości: 1