合成复用原则(Composite Reuse Principle, CRP),也被称作组合/聚合复用原则,它建议优先使用对象组合,而不是通过继承来复用代码。这个原则强调通过将对象组合成树形结构来实现代码复用,从而提供更大的灵活性。
肖哥弹架构 跟大家“弹弹” 代码设计技巧,需要代码关注
欢迎 点赞,点赞,点赞。

关注公号Solomon肖哥弹架构获取更多精彩内容
历史热点文章数据访问对象模式(Data Access Object Pattern):电商平台商品管理实战案例分析Holder模式(Holder Pattern):公司员工权限管理系统实战案例分析一个项目代码讲清楚DO/PO/BO/AO/E/DTO/DAO/ POJO/VO2. 合成复用原则设计图:3. 合成复用原则解决什么:合成复用原则解决了继承层次结构可能带来的问题,如脆弱的基类问题和不够灵活的扩展性。
4. 合成复用原则特点:灵活性:组合提供了更大的灵活性,可以动态地添加或移除组件。复用性:通过组合,可以在不同的地方复用相同的对象。5. 合成复用原则缺点:设计复杂性:可能需要更多的设计工作来确定合适的组件和它们之间的关系。性能考虑:在某些情况下,组合可能带来轻微的性能开销。6. 合成复用原则使用场景:当需要复用功能时,首先考虑是否可以使用对象组合来实现,而不是立即求助于继承。
7. 合成复用原则案例7.1 图形界面组件库案例图形界面组件库,需要实现各种按钮、文本框和面板等组件。
重构前:
public abstract class GUIComponent { public abstract void draw(); } public class Button extends GUIComponent { @Override public void draw() { // 绘制按钮 } } public class TextBox extends GUIComponent { @Override public void draw() { // 绘制文本框 } } // 使用GUIComponent的客户端代码 public class GUIClient { public void display() { new Button().draw(); new TextBox().draw(); } }
重构后
public interface Component { void draw(); void add(Component component); void remove(Component component); } public class Leaf implements Component { @Override public void draw() { // 具体的绘制逻辑 } @Override public void add(Component component) { // 叶子节点不支持添加子组件 } @Override public void remove(Component component) { // 叶子节点不支持移除子组件 } } public class Composite implements Component { private List<Component> components = new ArrayList<>(); @Override public void draw() { for (Component component : components) { component.draw(); } } @Override public void add(Component component) { components.add(component); } @Override public void remove(Component component) { components.remove(component); } } // 使用Component的客户端代码 public class GUIClient { public void display() { Composite panel = new Composite(); panel.add(new Button()); // 将按钮作为组件添加到面板 panel.add(new TextBox()); // 将文本框作为组件添加到面板 panel.draw(); } }
7.2 电商平台案例
允许用户浏览商品、将商品添加到购物车、下订单等。在这个系统中,商品可以是简单的单品,也可以是由多个商品组成的套餐。重构前,系统可能使用继承来处理商品和套餐,这可能导致一些问题,如脆弱的基类问题。
重构前:
public abstract class Product { protected String name; protected double price; public abstract double calculateTotalPrice(int quantity);}public class SimpleProduct extends Product { @Override public double calculateTotalPrice(int quantity) { return price quantity; }}public class BundleProduct extends Product { private List<Product> includedProducts; public BundleProduct() { includedProducts = new ArrayList<>(); } public void addProduct(Product product) { includedProducts.add(product); } @Override public double calculateTotalPrice(int quantity) { double total = 0; for (Product product : includedProducts) { total += product.calculateTotalPrice(quantity); } return total; }}
问题分析:
继承层次结构: SimpleProduct 和 BundleProduct 都继承自 Product 类,这限制了商品类型的扩展。脆弱的基类问题:如果需要修改 Product 类,可能会影响到所有子类。重构后:
public interface Product { double calculateTotalPrice(int quantity);}public class SimpleProduct implements Product { private String name; private double price; public SimpleProduct(String name, double price) { this.name = name; this.price = price; } @Override public double calculateTotalPrice(int quantity) { return price quantity; }}public class BundleProduct implements Product { private List<Product> includedProducts; public BundleProduct() { includedProducts = new ArrayList<>(); } public void addProduct(Product product) { includedProducts.add(product); } @Override public double calculateTotalPrice(int quantity) { double total = 0; for (Product product : includedProducts) { total += product.calculateTotalPrice(quantity); } return total; }}public class ShoppingCart { private List<Product> products; public ShoppingCart() { products = new ArrayList<>(); } public void addProduct(Product product) { products.add(product); } public double calculateTotalPrice() { double total = 0; for (Product product : products) { total += product.calculateTotalPrice(1); // Assume quantity is 1 for simplicity } return total; }}// 使用Product和ShoppingCart的客户端代码public class ECommerceClient { public static void main(String[] args) { SimpleProduct laptop = new SimpleProduct("Laptop", 1200.00); SimpleProduct mouse = new SimpleProduct("Mouse", 25.00); BundleProduct bundle = new BundleProduct(); bundle.addProduct(laptop); bundle.addProduct(mouse); ShoppingCart cart = new ShoppingCart(); cart.addProduct(bundle); System.out.println("Total price: " + cart.calculateTotalPrice()); }}
解决的问题:
使用接口而非继承: Product 接口提供了商品的契约,不同的商品类型通过实现该接口来复用代码。灵活性增强:新增商品类型(如 SubscriptionProduct)时,只需实现 Product 接口,无需修改现有类。解耦合: ShoppingCart 通过接口与商品交互,不关心商品的具体类型,提高了系统的解耦性。易于扩展:可以轻松添加新的商品特性,如折扣或优惠券,而不影响现有的商品实现。8. 参考开源框架:在Java Swing和.NET WPF等图形界面框架中,组件通常可以通过组合来构建复杂的用户界面。
9. 总结:合成复用原则通过对象组合提供了一种灵活的代码复用方式。相比继承,组合可以更好地应对变化,因为新增组件类型不需要修改现有类。此外,组合允许动态地添加或移除组件,使得系统更加灵活。虽然这可能会增加设计的复杂性,但它为构建可扩展和可维护的软件系统提供了强大的支持。遵循合成复用原则有助于创建更加模块化和灵活的系统。
历史热点文章享元模式(Flyweight Pattern):网页游戏中的角色对象管理实战案例分析观察者模式(Observer Pattern):股票交易系统实战案例分析策略模式(Strategy Pattern):电商平台的优惠券系统实战案例分析模板方法模式(Template Method Pattern):视频播放应用实战案例分析命令模式(Command Pattern):网络爬虫任务队列实战案例分析迭代器模式(Iterator Pattern):电商平台商品分类浏览实战案例分析中介者模式(Mediator Pattern):即时通讯软件实战案例分析备忘录模式(Memento Pattern):游戏存档系统实战案例分析状态模式(State Pattern):电商平台订单状态管理实战案例分析责任链模式(Chain of Responsibility Pattern):电商平台的订单审批流程实战案例分析访问者模式(Visitor Pattern):电商平台商品访问统计实战案例分析工厂方法模式(Factory Method Pattern): 电商多种支付实战案例分析抽象工厂模式(Abstract Factory Pattern):多风格桌面应用实战案例分析建造者模式(Builder Pattern): 在线订单系统实战案例分析原型模式(Prototype Pattern): 云服务环境配置实战案例分析适配器模式(Adapter Pattern):第三方支付集成实战案例分析装饰器模式(Decorator Pattern):电商平台商品价格策略实战案例分析单例模式(Singleton Pattern):购物车实战案例分析