面向对象编程中常会说「少用继承,多用组合」,于是让 ChatGPT
给出了一个具体的例子来说明。
我们假设有一个角色类,拥有攻击和防御的方法。我们可以通过继承来创建战士或弓箭手等具体的角色类型。下面是使用继承来实现的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| abstract class Character { public abstract void attack(); public abstract void defend(); }
class Warrior extends Character { @Override public void attack() { System.out.println("Warrior attacks with sword"); }
@Override public void defend() { System.out.println("Warrior defends with shield"); } }
class Archer extends Character { @Override public void attack() { System.out.println("Archer attacks with bow"); }
@Override public void defend() { System.out.println("Archer defends with agility"); } }
public class Main { public static void main(String[] args) { Character warrior = new Warrior(); warrior.attack(); warrior.defend();
Character archer = new Archer(); archer.attack(); archer.defend(); } }
|
这样做的问题是,我们之后每添加一个新的角色类型,都要创建一个 Character
的子类。如果我们需要改变父类的结构,有可能需要同步修改它的所有子类。而随着继承链增多,耦合度会变高。
而下面是使用组合的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| interface AttackBehavior { void attack(); }
interface DefenseBehavior { void defend(); }
class SwordAttack implements AttackBehavior { @Override public void attack() { System.out.println("Attacks with sword"); } }
class BowAttack implements AttackBehavior { @Override public void attack() { System.out.println("Attacks with bow"); } }
class ShieldDefense implements DefenseBehavior { @Override public void defend() { System.out.println("Defends with shield"); } }
class AgilityDefense implements DefenseBehavior { @Override public void defend() { System.out.println("Defends with agility"); } }
class Character { private AttackBehavior attackBehavior; private DefenseBehavior defenseBehavior;
public Character(AttackBehavior attackBehavior, DefenseBehavior defenseBehavior) { this.attackBehavior = attackBehavior; this.defenseBehavior = defenseBehavior; }
public void attack() { attackBehavior.attack(); }
public void defend() { defenseBehavior.defend(); } }
public class Main { public static void main(String[] args) { Character warrior = new Character(new SwordAttack(), new ShieldDefense()); warrior.attack(); warrior.defend();
Character archer = new Character(new BowAttack(), new AgilityDefense()); archer.attack(); archer.defend(); } }
|
这样的写法代码实现相对复杂,但是整体上变得更加灵活了,其拓展性更强。我们定义好不同的攻击和防御行为后,每新创建一个角色类型,都不需要再额外创建一个类,只需要选择合适的行为进行组合即可。