【设计模式】合成复用原则(Composite Reuse Principle)

合成复用原则是指:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。通常类的复用分为继承复用和合成复用两种。

继承复用虽然有简单和易实现的优点,但它也存在以下缺点:

  1. 继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为白箱复用。
  2. 子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
  3. 它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。

采用组合或聚合复用时,可以将已有对象纳入新对象中,使之成为新对象的一部分,新对象可以调用已有对象的功能,它有以下优点:

  1. 它维持了类的封装性。因为成分对象的内部细节是新对象看不见的,所以这种复用又称为“黑箱”复用。
  2. 对象间的耦合度低。可以在类的成员位置声明抽象。
  3. 复用的灵活性高。这种复用可以在运行时动态进行,新对象可以动态地引用与成分对象类型相同的对象。

1 案例分析(汽车分类管理)

汽车按动力源划分可分为汽油汽车、电动汽车等;按颜色划分可分为白色汽车、黑色汽车和红色汽车等。如果同时考虑这两种分类,其组合就很多。

using System;

namespace DesignPattern
{
    internal static class Program
    {
        public static void Main(string[] args)
        {
            new RedPetrolCar().Move();
            new RedElectricCar().Move();
            new WhitePetrolCar().Move();
            new WhiteElectricCar().Move();
        }
    }
    
    /// <summary>
    /// 抽象汽车类
    /// </summary>
    public abstract class Car
    {
        /// <summary>
        /// 行驶功能
        /// </summary>
        public abstract void Move();
    }

    /// <summary>
    /// 汽油车类
    /// </summary>
    public abstract class PetrolCar : Car
    {
    }

    /// <summary>
    /// 电动汽车类
    /// </summary>
    public abstract class ElectricCar : Car
    {
    }

    /// <summary>
    /// 红色汽油汽车类
    /// </summary>
    public class RedPetrolCar : PetrolCar
    {
        /// <summary>
        /// <inheritdoc cref="Move"/>
        /// </summary>
        public override void Move() => Console.WriteLine(nameof(RedPetrolCar));
    }

    /// <summary>
    /// 白色汽油汽车类
    /// </summary>
    public class WhitePetrolCar : PetrolCar
    {
        /// <summary>
        /// <inheritdoc cref="Move"/>
        /// </summary>
        public override void Move() => Console.WriteLine(nameof(WhitePetrolCar));
    }

    /// <summary>
    /// 红色电动汽车类
    /// </summary>
    public class RedElectricCar : ElectricCar
    {
        /// <summary>
        /// <inheritdoc cref="Move"/>
        /// </summary>
        public override void Move() => Console.WriteLine(nameof(RedPetrolCar));
    }

    /// <summary>
    /// 白色电动汽车类
    /// </summary>
    public class WhiteElectricCar : ElectricCar
    {
        /// <summary>
        /// <inheritdoc cref="Move"/>
        /// </summary>
        public override void Move() => Console.WriteLine(nameof(WhitePetrolCar));
    }
}

如果此时研发了一种新型能源(例如,氢能源)的汽车,该类型汽车又有红色和白色两个种类,这样就需要另外定义HydrogenCar:CarRedHydrogenCar:HydrogenCarWhiteHydrogenCar:HydrogenCar,易造成类爆炸

2 案例改进

using System;

namespace DesignPattern
{
    internal static class Program
    {
        public static void Main(string[] args)
        {
            new PetrolCar() {Color = new WhiteColor()}.Move();
            new ElectricCar() {Color = new RedColor()}.Move();
        }
    }
    
    /// <summary>
    /// 颜色接口
    /// </summary>
    public interface IColor
    {
        string Name {get;}
    }

    /// <summary>
    /// 红色
    /// </summary>
    public class RedColor : IColor
    {
        public string Name => "Red";
    }

    /// <summary>
    /// 白色
    /// </summary>
    public class WhiteColor : IColor
    {
        /// <summary>
        /// 颜色
        /// </summary>
        public string Name => "Red";
    }

    /// <summary>
    /// 抽象汽车类
    /// </summary>
    public abstract class Car
    {
        /// <summary>
        /// 聚合颜色属性
        /// </summary>
        public IColor Color {get;set;}
        
        /// <summary>
        /// 行驶功能
        /// </summary>
        public abstract void Move();
    }

    /// <summary>
    /// 汽油车类
    /// </summary>
    public class PetrolCar : Car
    {
        /// <summary>
        /// <inheritdoc cref="Move"/>
        /// </summary>
        public override void Move() => Console.WriteLine($"{this.Color.Name} {nameof(PetrolCar)} is " + nameof(Move));
    }

    /// <summary>
    /// 电动车类
    /// </summary>
    public class ElectricCar : Car
    {
        /// <summary>
        /// <inheritdoc cref="Move"/>
        /// </summary>
        public override void Move() => Console.WriteLine($"{this.Color.Name}  {nameof(ElectricCar)} is " + nameof(Move));
    }
}

通过聚合关系,减少了类数量。如果增加新型能源的汽车,只需要增加一个类HydrogenCar

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhy29563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值