首页 > 其他分享 >合成复用原则:桌面系统与电商系统中构建灵活的软件设计方案

合成复用原则:桌面系统与电商系统中构建灵活的软件设计方案

时间:2024-07-12 14:28:22浏览次数:17  
标签:Product 软件设计 Pattern void 复用 案例 电商 public

在这里插入图片描述

合成复用原则(Composite Reuse Principle, CRP),也被称作组合/聚合复用原则,它建议优先使用对象组合,而不是通过继承来复用代码。这个原则强调通过将对象组合成树形结构来实现代码复用,从而提供更大的灵活性。

肖哥弹架构 跟大家“弹弹” 代码设计技巧,需要代码关注

欢迎 点赞,点赞,点赞。

关注公号Solomon肖哥弹架构获取更多精彩内容

历史热点文章

2. 合成复用原则设计图:

在这里插入图片描述

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;
    }
}

问题分析:

  1. 继承层次结构SimpleProductBundleProduct 都继承自 Product 类,这限制了商品类型的扩展。
  2. 脆弱的基类问题:如果需要修改 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());
    }
}

解决的问题:

  1. 使用接口而非继承Product 接口提供了商品的契约,不同的商品类型通过实现该接口来复用代码。
  2. 灵活性增强:新增商品类型(如 SubscriptionProduct)时,只需实现 Product 接口,无需修改现有类。
  3. 解耦合ShoppingCart 通过接口与商品交互,不关心商品的具体类型,提高了系统的解耦性。
  4. 易于扩展:可以轻松添加新的商品特性,如折扣或优惠券,而不影响现有的商品实现。
8. 参考开源框架:

在Java Swing和.NET WPF等图形界面框架中,组件通常可以通过组合来构建复杂的用户界面。

9. 总结:

合成复用原则通过对象组合提供了一种灵活的代码复用方式。相比继承,组合可以更好地应对变化,因为新增组件类型不需要修改现有类。此外,组合允许动态地添加或移除组件,使得系统更加灵活。虽然这可能会增加设计的复杂性,但它为构建可扩展和可维护的软件系统提供了强大的支持。遵循合成复用原则有助于创建更加模块化和灵活的系统。

历史热点文章

标签:Product,软件设计,Pattern,void,复用,案例,电商,public
From: https://blog.csdn.net/alises1314/article/details/140376172

相关文章

  • 多路复用IO
    简单实现的socket-CSDN博客        在上面的文章中,我们使用socket(创建)、bind(绑定)、listen(监听)、accept(接收)这四个函数,讲了如何利用socket创建一个网络套接字,并在文章结尾实现了一个简单的多进程服务器。多进程服务器:每当有一个新的客户端建立连接,就会创建一......
  • SSM电商微信小程序 毕业设计-附源码09228
    摘 要随着微信小程序的使用越来越广泛,在传统的商业模式中,对于各类生活日常商品,人们习惯于到各种商家店铺购买。然而在快节奏的新时代中,人们不一定能为购买商品腾出时间,更不会耐心挑选自己想要的商品。所以设计一个电商微信小程序,既是迎合电子商务的大潮流,也是传统商品行业......
  • 软件设计13丨结构化编程:为什么做设计时仅有结构化编程是不够的?
    上一讲,我们讲到了编程范式,现在开发的一个重要趋势就是多种编程范式的融合,显然,这就要求我们对各种编程范式都有一定的理解。从这一讲开始,我们就展开讨论一下几个主要的编程范式。首先,我们来讨论程序员们最熟悉的编程范式:结构化编程。很多人学习编程都是从C语言起步的,C语言......
  • 软件设计12丨编程范式:明明写的是Java,为什么被人说成了C代码?
    在上一个小模块,我给你讲了程序设计语言,帮助你重新审视一下自己最熟悉的日常工具。但是,使用程序设计语言是每个程序员都能做到的,可写出的程序却是千差万别的。这一讲,我们就来看看这些差异到底是怎样造成的。在开始之前,我先给你讲一个小故事。在一次代码评审中,小李兴致勃勃地......
  • [Java并发]IO多路复用
    IOIO多路复用BIONIOselectpollepoll水平触发和边沿触发水平触发只关心文件描述符中是否还有没完成处理的数据,如果有,不管怎样epoll_wait,总是会被返回。简单说——水平触发代表了一种“状态”。边沿触发只关心文件描述符是否有新的事件产生,如果有,则返回;如果返回过一次,......
  • 深度解读昇腾CANN内存复用技术,降低网络内存占用
    本文分享自华为云社区《深度解读昇腾CANN内存复用技术,降低网络内存占用》,作者:昇腾CANN。随着大模型的兴起,神经网络规模不断扩大,对内存资源的消耗也越来越高,如何降低AI算法的内存占用成为AI计算领域降成本提性能的一个重要手段。当前降低AI算法内存占用的主要技术有内存复用(Memor......
  • 软件设计中 高扇入,高扇出是啥?
    在软件设计和架构中,“高扇入”(HighFan-In)是一个重要的概念,它描述了一个模块或组件被其他模块或组件调用的频率和广度。具体来说:高扇入(HighFan-In)定义:高扇入是指一个模块或组件被多个其他模块或组件调用或依赖的情况。这意味着该模块是一个常用的功能模块,很多其他模块都依赖......
  • 软件设计之Java入门视频(13)
    软件设计之Java入门视频(13)视频教程来自B站尚硅谷:尚硅谷Java入门视频教程,宋红康java基础视频相关文件资料(百度网盘)提取密码:8op3idea下载可以关注软件管家公众号学习内容:该视频共分为1-717部分本次内容涉及360-389在写代码时,总是需要来回切换界面来看代码要求......
  • 24年软件设计师!看这篇就够了(规划+知识点)
    祝大家逢考必过~一,关于软考:考试时间:    一年有两次软考,一般是五月末和十一月的中旬,具体时间官网通知:中国计算机技术职业资格网中国计算机技术职业资格网https://www.ruankao.org.cn/exam/plan考试时长:        考试总时长240min      ......
  • 主流电商平台(淘+猫+京)营销中大数据的应用◆
    随着经济的不断发展,网络信息技术不断加强,电子商务和大数据的蓬勃发展极大地方便了人们的生活。本文章主要阐述大数据分析与电商营销的含义、大数据分析在电子商务营销中的应用,以及该应用的作用和存在哪些不足及解决方法。探究大数据分析在电子商务营销中的应用对行业发展具有重要......