How to figure out design pattern for this particular solution?

While working on a project I’ve come up with some design solution. I am having a hard time relating it to any general design pattern or analyzing this situation in details. This is also prohibiting me to find any better design for this.

This is a simple analogy of my solution –
Both Kangaroo and Tiger can walk but only Kangaroo can jump and only Tiger can run.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Animal<TLeg> where TLegs: ILegs
{
TLegs Legs;
void Walk(){ Legs.Walk(); }
}
Kangaroo: Animal<IJumpingLegs>
{
void Jump() { Legs.Jump(); }
}
Tiger: Animal<IRunningLegs>
{
void Run() { Legs.Run(); }
}
ILegs
{
void Walk();
}
IRunningLegs : ILegs
{
void Run();
}
IJumpingLegs : Ilegs
{
void Jump();
}
</code>
<code>Animal<TLeg> where TLegs: ILegs { TLegs Legs; void Walk(){ Legs.Walk(); } } Kangaroo: Animal<IJumpingLegs> { void Jump() { Legs.Jump(); } } Tiger: Animal<IRunningLegs> { void Run() { Legs.Run(); } } ILegs { void Walk(); } IRunningLegs : ILegs { void Run(); } IJumpingLegs : Ilegs { void Jump(); } </code>
Animal<TLeg> where TLegs: ILegs
{
    TLegs Legs;
    void Walk(){ Legs.Walk(); }
}

Kangaroo: Animal<IJumpingLegs>
{
    void Jump() { Legs.Jump(); }
}

Tiger: Animal<IRunningLegs>
{
    void Run() { Legs.Run(); }
}

ILegs
{
   void Walk();
}

IRunningLegs : ILegs
{
   void Run();
}

IJumpingLegs : Ilegs
{
   void Jump();
}

[Edit]
Problem Description:
Here, Kangaroo and Tiger share common functions and a property Legs. Therefore, I have a base class for common functions. Base class needs to have access to this property Legs.
Functions in subclasses too rely on Legs and based on type of Legs, subclass will need to call different functions of this property.

Basically, two concrete animals need some common methods and their uncommon methods(Jump and Run) require different TYPE of a common property.

For this problem, I have come up with the solution described above. Hoping that I am able to describe my problem, I would like to know if there could be any alternate solution.

Does this problem/solution sound familiar? Is there anything that can be improved?

3

This described problem reminds me the Adapter and Facade Patterns: Being Adaptive.

While reading your question, i also have remembered a famous funny old saying:

If it walks like a duck and quacks like a duck, then it must be a turkey wrapped with a duck adapter…

You may get detailed explanation from the following book – Head First Design Patterns

In addition, there are SOLID principles and Liskov Substitution Principle is one of them. It also addresses this issue with a different flavor.

If it looks like a duck, quacks like a duck, but needs batteries – you probably have the wrong abstraction

2

It is a mistake to use inheritance with the Legs classes and interfaces.(But if your teacher/boss insists that you have to…you’ll probably have to give in.)

Your design works well enough for the requirements you listed. But suppose there is a Horse that can both run and jump. How do you implement that?

I suggest that WalkingLegs, RunningLegs, and JumpingLegs should all be separate classes with no inheritance. The Tiger would have WalkingLegs and RunningLegs, the Kangaroo would have WalkingLegs and JumpingLegs, and the Horse would have all three.

The above suggestion confuses the Legs metaphor. What we are really modeling is behavior, not types of legs.

Using classes to represent a behavior is part of the strategy pattern. In the strategy pattern, behaviors have different implementations (in this example, different implements of walking, jumping, etc.)

2

To me, it seems like case of bad abstraction. Base classes are for abstracting behavior that is same for all expected children. Which is wrong in your example. In your case you either want Move virtual method, and then override it in concrete animals. Or you want Jump and Run methods, but then there is nothing common between them, so abstracting it away doesn’t make sense.

And there is one rule I like when doing this :

Abstractions should always be seen from point of who will use those abstractions. Not from the inside of the implementation.

If you are writing some abstraction and you haven’t written code that will use this abstraction, then you are doing something wrong.

1

I would probably implement something along the lines of this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>public abstract class Animal: ILegs
{
public virtual void Walk(){/*Base logic for walking*/}
}
public interface ILegs
{
void Walk();
}
public interface IJumpingLegs
{
void Jump();
}
public interface IRunningLegs
{
void Run();
}
public class Kangeroo : Animal, IJumpingLegs
{
public void Jump()
{
//Logic for Jumping
}
}
public class Tiger : Animal, IRunningLegs
{
public void Run()
{
//Logic for Jumping
}
}
//Custom Implementation
public class OtherAnimal : Animal
{
public override void Walk() { /*Custom how I walk*/ }
}
</code>
<code>public abstract class Animal: ILegs { public virtual void Walk(){/*Base logic for walking*/} } public interface ILegs { void Walk(); } public interface IJumpingLegs { void Jump(); } public interface IRunningLegs { void Run(); } public class Kangeroo : Animal, IJumpingLegs { public void Jump() { //Logic for Jumping } } public class Tiger : Animal, IRunningLegs { public void Run() { //Logic for Jumping } } //Custom Implementation public class OtherAnimal : Animal { public override void Walk() { /*Custom how I walk*/ } } </code>
public abstract class Animal: ILegs
{
    public virtual void Walk(){/*Base logic for walking*/}
}

public interface ILegs
{
    void Walk();
}

public interface IJumpingLegs
{
    void Jump();
}

public interface IRunningLegs
{
    void Run();
}

public class Kangeroo : Animal, IJumpingLegs
{
    public void Jump()
    {
        //Logic for Jumping
    }
}

public class Tiger : Animal, IRunningLegs
{
    public void Run()
    {
        //Logic for Jumping
    }
}


//Custom Implementation
public class OtherAnimal : Animal
{
    public override void Walk() { /*Custom how I walk*/ }
}

When instanciating my objects I would use

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>OtherAnimal a = new OtherAnimal();
a.Walk(); //Custom override logic fro OtherAnimal class
Tiger t = new Tiger();
t.Run(); //Custom Run logic
t.Walk(); //Logic from Animal abstract class
</code>
<code>OtherAnimal a = new OtherAnimal(); a.Walk(); //Custom override logic fro OtherAnimal class Tiger t = new Tiger(); t.Run(); //Custom Run logic t.Walk(); //Logic from Animal abstract class </code>
OtherAnimal a = new OtherAnimal();
a.Walk(); //Custom override logic fro OtherAnimal class

Tiger t = new Tiger();
t.Run();  //Custom Run logic
t.Walk(); //Logic from Animal abstract class

Each Tiger/Kangeroo class only implements the necessary interface for each class and is not inheriting any unnecessary logic and not breaking the Liskov Substitution Principle mentioned by @Yusubov.

The Tiger/Kangeroo class also use the base Walk() logic from the Animal abstract class and have the option if necessary to override it lie the OtherAnimal class does.

Just don’t implement a Fish class or similar extending the Animal. Fish don’t walk, or have Legs!!

4

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật