JavaRush /Java блогы /Random-KK /Java-дағы мұраға қарсы композиция
dio
Деңгей
Москва

Java-дағы мұраға қарсы композиция

Топта жарияланған
Бұл мақала Java тіліндегі мұра және композиция ұғымдарын суреттейді. Бірінші мысал мұраны көрсетеді, содан кейін құрам арқылы мұра дизайнын жақсарту жолын көрсетеді. Біз олардың арасында қалай таңдауға болатынын соңында қорытындылаймыз. Java тіліндегі мұраға қарсы композиция - 1

1. Мұрагерлік

Бізде сынып бар деп есептейік Insect(ағылшынша жәндіктер) Бұл сыныпта екі әдіс бар: 1. move()(ағылшын тілінен move) және 2. attack()(ағылшынша шабуылдан)
class Insect {
	private int size;
	private String color;

	public Insect(int size, String color) {
		this.size = size;
		this.color = color;
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public void move() {
		System.out.println("Move");
	}

	public void attack() {
		move(); //assuming an insect needs to move before attacking
		System.out.println("Attack");
	}
}
Енді сіз классты (ағылшынша аары) анықтағыңыз келеді Bee, оның түрлерінің бірі болып табылады Insect, бірақ attack()және әртүрлі іске асырулары бар move(). Мұны мұраны пайдалану арқылы жасауға болады:
class Bee extends Insect {
	public Bee(int size, String color) {
		super(size, color);
	}

	public void move() {
		System.out.println("Fly");
	}

	public void attack() {
		move();
		super.attack();
	}
}
public class InheritanceVSComposition {
	public static void main(String[] args) {
		Insect i = new Bee(1, "red");
		i.attack();
	}
}
Класс иерархиялық диаграммасы өте қарапайым: Java тіліндегі мұраға қарсы композиция - 2Орындалу нәтижесі:
Fly
Fly
Attack
«Ұшу» екі рет теріледі, сондықтан әдіс move()екі рет шақырылады. Бірақ оны тек бір рет шақыру керек. Мәселе мынадан туындайды super.attack(). Әдіс класс әдісін attack ()шақырады . Ішкі класс шақырғанда , ол қайта анықталған әдісті де шақырады . Мәселені шешу үшін біз: move()Insectsuper.attack ()move()
  1. Ішкі класс әдісін жойыңыз attack(). Бұл ішкі сыныпты суперсынып әдісін іске асыруға тәуелді етеді attack(). Егер attack()attack()суперкласс жылжытудың басқа әдісін қолдана бастаса, ішкі сыныпты да өзгерту қажет болады. Бұл нашар инкапсуляция.
  2. Әдісті attack()келесідей қайта жазыңыз:

    public void attack() {
    	move();
    	System.out.println("Attack");
    }
  3. Бұл дұрыс нәтижеге кепілдік береді, себебі ішкі сынып енді суперклассқа тәуелді емес. Дегенмен, code суперкласстың көшірмесі болып табылады. (әдіс attack()жолды шығарудан гөрі күрделірек нәрселерді жасайды). Бұл бағдарламалық жасақтаманың жақсы дизайны емес және қайталанатын code болмауы керек.

Бұл мұра дизайны нашар, себебі ішкі сынып оның суперклассының іске асыру мәліметтеріне байланысты. Егер суперкласс өзгерсе, ішкі сынып дұрыс жұмыс істемейді.

2. Құрамы

Мұрагерлік орнына композицияны пайдалануға болады. Оны қолданатын шешімді қарастырайық. Функция attack()интерфейс ретінде абстракцияланады.
interface Attack {
	public void move();
	public void attack();
}
Шабуыл интерфейсін енгізу арқылы шабуылдың әртүрлі түрлерін анықтауға болады.
class AttackImpl implements Attack {
	private String move;
	private String attack;

	public AttackImpl(String move, String attack) {
		this.move = move;
		this.attack = attack;
	}

	@Override
	public void move() {
		System.out.println(move);
	}

	@Override
	public void attack() {
		move();
		System.out.println(attack);
	}
}
Шабуыл функциясы сыртқы болғандықтан, сынып Insectоны енді қамтымайды.
class Insect {
	private int size;
	private String color;

	public Insect(int size, String color) {
		this.size = size;
		this.color = color;
	}

	public int getSize() {
		return size;
	}

	public void setSize(int size) {
		this.size = size;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
}
Класс Bee(ағылшын тілінен Bee), тип қалай Insectшабуыл жасай алады.
// This wrapper class wrap an Attack object
class Bee extends Insect implements Attack {
	private Attack attack;

	public Bee(int size, String color, Attack attack) {
		super(size, color);
		this.attack = attack;
	}

	public void move() {
		attack.move();
	}

	public void attack() {
		attack.attack();
	}
}
Сынып диаграммасы: Java тіліндегі мұраға қарсы композиция - 3
public class InheritanceVSComposition2 {
	public static void main(String[] args) {
		Bee a = new Bee(1, "black", new AttackImpl("fly", "move"));
		a.attack();

		// if you need another implementation of move()
		// there is no need to change Insect, we can quickly use new method to attack

		Bee b = new Bee(1, "black", new AttackImpl("fly", "sting"));
		b.attack();
	}
}
Орындау нәтижесі:
fly
move
fly
sting

3. Бұл тәсілдерді қашан қолдану керек?

Төмендегі 2 тармақ мұра мен құрам арасында шешім қабылдауға көмектеседі:
  1. Егер сіз «IS» пішімінің сыныптары арасындағы қарым-қатынаспен айналысатын болсаңыз және сынып оның барлық интерфейстерін басқа сыныпқа бергісі келсе, мұрагерлік жақсырақ.
  2. егер қатынас «HAS» болса, онда композицияға артықшылық беріледі.
Осылайша, тұқым қуалаушылық пен құрамның өзіндік қосымшалары бар және олардың артықшылықтарын түсіну керек. Сілтемелер:
  1. Блох, Джошуа. Тиімді java. Pearson Education Үндістан, 2008 ж
  2. https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance
  3. https://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should...
Түпнұсқа мақалаға сілтеме аударылды
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION