I'm facing a similar scenario to this issue and I was wondering if it's possible to get around a cleaner solution.
Supposing we have a party that has People on it, We have the interface:
public interface IPerson {
void Arrive();
void Dance();
}
And its implementations, people that are able to dance
public class PersonThatCanDance : IPerson {
public void Arrive() {
//Logic related to arriving
}
public void Dance() {
//Logic related to dancing
}
}
and those who aren't
public class PersonThatCannotDance : IPerson {
public void Arrive() {
//Logic related to arriving
}
public void Dance() {
}
}
Knowing this, now we have the party with 2 people
public class Party {
private IPerson person1;
private IPerson person2
private void StartParty() {
person1.Arrive();
person2.Arrive();
}
private void StartMusic() {
person1.Dance();
person2.Dance();
}
}
With this scenario settled, the problem comes when we want to make the party not care if the person is a person that can dance or not. The party throws the people into dancing no matter if they have functionality to do so.
From what I understand, the existence of the Dance() method in PersonThatCannotDance is a violation of ISP but making the party not care about what kind of person is preventing me from respecting the principle.
Is there a way to get around this? Thank you.
CodePudding user response:
There is not enough information to determine the right design for your situation, but I can offer a design that's broadly applicable:
public interface IPerson {
void Arrive();
}
public class PersonThatCanDance : IPerson {
public void Arrive(Party party) {
//Logic related to arriving
party.AddDancers(this);
}
public void Dance() {
//Logic related to dancing
}
}
public class PersonThatCannotDance : IPerson {
public void Arrive(Party party) {
//Logic related to arriving
}
}
public class Party {
private IPerson person1;
private IPerson person2;
ArrayList dancers = new ArrayList();
private void StartParty() {
person1.Arrive(this);
person2.Arrive(this);
}
public void AddDancers(PersonThatCanDance dancer) {
dancers.Add(dancer);
}
private void StartMusic() {
for (var dancer in dancers) {
dancer.Dance();
}
}
}
A possibly more idiomatic alternative, is going by events.
public class PersonThatCanDance : IPerson {
public void Arrive(Party party) {
//Logic related to arriving
party.OnCueMusic(this.Dance);
}
...
}
public class Party {
public delegate void Dance();
ArrayList musicEvents = new ArrayList();
...
public void OnCueMusic(Dance dance) {
musicEvents.Add(dance);
}
private void StartMusic() {
for (var musicEvent in musicEvents) {
musicEvent();
}
}
}
CodePudding user response:
yes you are right. it is violation of ISP.
public interface IArrive : IPerson {
void Arrive();
DateTime Time {get;set;}
string Mode {get;set;}
}
public interface IDance: IPerson {
void Dance();
DateTime duration {get;set;}
string Type {get;set;}
}
public interface IPerson {
string Name {get;set;}
void Dress();
}
Now Implementations looks like this, people that are able to dance
public class PersonThatCanDance : IArrive,IDance {
string Name {get; set;}
public void Dress() {
//Logic related to arriving
}
public void Arrive() {
//Logic related to arriving
}
public void Dance() {
//Logic related to dancing
}
}
and those who aren't
public class PersonThatCannotDance : IArrive {
string Name {get; set;}
public void Dress() {
//Logic related to arriving
}
public void Arrive() {
//Logic related to arriving
}
}
In Party Class
public class Party {
private IPerson person1 = new PersonThatCanDance();
private IPerson person2 = new PersonThatCannotDance();
private void StartParty() {
((IArrive)person1).Arrive();
((IArrive)person2).Arrive();
}
private void StartMusic() {
if(person1 is IDance)
{
((IDance)person1).Dance();
}
if(person2 is IDance)
{
((IDance)person2).Dance();
}
}
}
Now I hope this solution will work. please let me know if still have doubt.