zoukankan      html  css  js  c++  java
  • 软件工程六大设计原则总结,案例演示

    本文源码:GitHub·点这里 || GitEE·点这里

    一、单一职责原则

    1、概念描述

    对类来说的,即一个类应该只负责一项职责。如果一个类负责两个职责,可能存在职责1变化,引起职责2变化的情况。可以基于抽象逻辑,或者业务逻辑对类进行细化。

    2、案例演示

    这里基于方法和类的细化都可以,可以根据实际业务选择。

    class Animal {
        public void dogVoice (){
            System.out.println("狗叫声:旺旺");
        }
        public void cowVoice (){
            System.out.println("牛叫声:哞哞");
        }
    }
    class DogVoice {
        public String getDogVoice (){
            return "旺旺" ;
        }
    }
    class CowVoice {
        public String getCowVoice (){
            return "哞哞" ;
        }
    }
    

    3、注意事项

    减少代码一处变更引起的程序大规模改动情况,降低类的复杂度,提高类的可读性,可维护性。通常情况下,需要遵守单一职责原则,可以适当违反单一职责原则。

    二、接口隔离原则

    1、概念描述

    客户端不应该依赖它不需要的接口,一个类对另一个类的依赖,应该建立在最小的接口上。

    2、案例演示

    interface ReadBlog {
        String getBlog () ;
    }
    interface AdminBlog {
        Boolean insertBlog () ;
        Boolean updateBlog () ;
        Boolean deleteBlog () ;
    }
    /**
     * 读者只开放博客阅读接口
     */
    class Reader implements ReadBlog {
        @Override
        public String getBlog() {
            return null;
        }
    }
    /**
     * 管理员有博客全部的管理权限
     */
    class AdminUser implements AdminBlog,ReadBlog {
        @Override
        public String getBlog() {
            return null;
        }
        @Override
        public Boolean insertBlog() {
            return null;
        }
        @Override
        public Boolean updateBlog() {
            return null;
        }
        @Override
        public Boolean deleteBlog() {
            return null;
        }
    }
    

    3、注意事项

    接口的设计粒度越小,则应用系统程序越灵活,程序变得灵活也就意味同时结构复杂性提高,开发开发和理解的难度也会变大,可维护性降低。

    三、依赖倒转原则

    1、概念描述

    高层模块不应该依赖低层模块,两者应依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象;中心思想是面向接口编程。

    2、案例演示

    public class C01_FarmFactory {
        public static void main(String[] args) {
            Animal animal = new Dog() ;
            FarmFactory farm = new Farming() ;
            farm.breed(animal) ;
            animal = new Pig() ;
            farm.breed(animal) ;
        }
    }
    /**
     * 接口声明依赖对象
     */
    interface FarmFactory {
        void breed (Animal animal) ;
    }
    class Farming implements FarmFactory {
        @Override
        public void breed(Animal animal) {
            System.out.println("农场饲养:"+animal.getAnimalName());
        }
    }
    interface Animal {
        String getAnimalName () ;
    }
    class Dog implements Animal {
        @Override
        public String getAnimalName() {
            return "牧羊犬";
        }
    }
    class Pig implements Animal {
        @Override
        public String getAnimalName() {
            return "土猪一号";
        }
    }
    

    3、注意事项

    相对于系统开发的多变性,抽象的相对稳定。以抽象为基础搭建的架构比以细节为基础的架构要稳定灵活。下层模块尽量都要有抽象类或接口,程序稳定性更好。变量的声明类型尽量是抽象类或接口,这样变量引用和实际对象之间存在一个过渡空间,利于程序扩展和优化。

    四、里氏替换原则

    1、概念描述

    假设如下场景:

    • 存在,一个类型T1,和实例的对象O1
    • 存在,一个类型T2,和实例的对象O2

    如果将所有类型为T1的对象O1都替换成类型T2的对象O2,程序的行为不发生改变。那么类型T2是类型T1的子类型。换句话说,所有引用基类的地方必须能透明地使用其子类的对象。

    2、案例演示

    public class C01_Calculate {
        public static void main(String[] args) {
            BizCalculate bizCalculate = new BizCalculate() ;
            System.out.println(bizCalculate.add(2,3));
        }
    }
    class Calculate { }
    class BaseCalculate extends Calculate {
        public int add (int a,int b){
            return a+b;
        }
    }
    /**
     * 这里使用组合的方式完成计算
     */
    class BizCalculate extends Calculate {
        private BaseCalculate baseCalculate = new BaseCalculate() ;
        public int add (int a,int b){
            return this.baseCalculate.add(a,b);
        }
    }
    

    3、注意事项

    使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法;子类可以扩展父类的功能,但不能改变原有父类的功能;在适当的情况下,可以通过聚合,组合,依赖等方式解决问题。

    五、开闭原则

    1、概念描述

    开闭原则是编程中最基础、最重要的设计原则,在代码结构的设计设计时,应该考虑对扩展开放,对修改关闭,抽象思维搭建结构,具体实现扩展细节。

    2、案例演示

    public class C01_BookPrice {
        public static void main(String[] args) {
            ParityBook parityBook = new DiscountBook("Java",100.00) ;
            System.out.println(parityBook.getPrice());
        }
    }
    interface Book {
        String getName () ;
        Double getPrice () ;
    }
    /**
     * 平价书籍
     */
    class ParityBook implements Book {
        private String name ;
        private Double price ;
        public ParityBook(String name, Double price) {
            this.name = name;
            this.price = price;
        }
        @Override
        public String getName() {
            return this.name ;
        }
        @Override
        public Double getPrice() {
            return this.price ;
        }
    }
    /**
     * 打折数据扩展价格计算策略
     */
    class DiscountBook extends ParityBook {
        public DiscountBook(String name, Double price) {
            super(name, price);
        }
        @Override
        public Double getPrice() {
            double oldPrice = super.getPrice();
            return oldPrice * 0.8 ;
        }
    }
    

    3、注意事项

    基于开闭原则设计的代码结构可以提高复用性和可维护性,通过接口或抽象类可以约束类的变化行为,基于指定策略对变化行为进行封装,并且能够实现对扩展开放,使用设计模式的基本原则就是遵循开闭原则。

    六、迪米特原则

    1、概念描述

    迪米特原则又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public方法,不对外开放任何信息。类与类关系越密切,耦合度越大,耦合的方式很多,依赖,关联,组合,聚合等。

    • 直接朋友概念

    两个对象之间有耦合关系,就说这两个对象之间是朋友关系。其中出现成员变量,方法参数,方法返回值中的类称为直接朋友,而出现在局部变量中的类不是直接朋友。从原则上说,陌生的类最好不要以局部变量的形式出现在类的内部。

    2、案例演示

    public class C01_Employee {
        public static void main(String[] args) {
            HeadCompanyEmpManage empManage = new HeadCompanyEmpManage() ;
            BranchCompanyEmpManage branchEmp = new BranchCompanyEmpManage() ;
            empManage.printEmp(branchEmp);
        }
    }
    /**
     * 总公司员工
     */
    class HeadCompanyEmp {
        public String name ;
        public HeadCompanyEmp(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "HeadCompanyEmp{name='" + name + '}';
        }
    }
    /**
     * 分公司员工
     */
    class BranchCompanyEmp {
        public String name ;
        public BranchCompanyEmp(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "BranchCompanyEmp{name='" + name + '}';
        }
    }
    /**
     * 分公司员工管理
     */
    class BranchCompanyEmpManage {
        // 添加分公司员工
        public List<BranchCompanyEmp> addEmp (){
            List<BranchCompanyEmp> list = new ArrayList<>() ;
            for (int i = 1 ; i <= 3 ; i++){
                list.add(new BranchCompanyEmp("分公司员工"+i)) ;
            }
            return list ;
        }
        // 获取分公司员工
        public void printBranchCompanyEmp (){
            List<BranchCompanyEmp> list = addEmp () ;
            for (BranchCompanyEmp emp:list){
                System.out.println(emp);
            }
        }
    }
    /**
     * 总公司员工管理,基于迪米特原则,不出现陌生类
     */
    class HeadCompanyEmpManage {
        // 添加总公司员工
        public List<HeadCompanyEmp> addHeadEmp (){
            List<HeadCompanyEmp> list = new ArrayList<>() ;
            for (int i = 1 ; i <= 3 ; i++){
                list.add(new HeadCompanyEmp("总公司员工"+i)) ;
            }
            return list ;
        }
        public void printEmp (BranchCompanyEmpManage empManage){
            // 打印分公司员工
            empManage.printBranchCompanyEmp();
            List<HeadCompanyEmp> headEmpList = addHeadEmp () ;
            for (HeadCompanyEmp headCompanyEmp:headEmpList){
                System.out.println(headCompanyEmp);
            }
        }
    }
    

    3、注意事项

    迪米特原则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此可以降低耦合关系。降低耦合关系,并不是要求完全没有依赖关系,过度的使用迪米特原则,容易产生大量的中间类,导致复杂度变大。所以在使用迪米特原则时要根据实际业务权衡。

    七、设计原则总结

    设计模式和设计原则的核心思想都是:判断业务应用中可能会变化模块,并且把这些模块独立出来,基于指定的策略进行封装,不要和那些变化的不大的模块耦合在一起,封装思想上基于接口和抽象类,而不是针对具体的实现编程。核心目的就是降低交互对象之间的松耦合度。设计模式和原则都不是可以生搬硬套的公式,个人理解:只要形似,神韵就自然不差。

    八、源代码地址

    GitHub·地址
    https://github.com/cicadasmile/model-arithmetic-parent
    GitEE·地址
    https://gitee.com/cicadasmile/model-arithmetic-parent
    

  • 相关阅读:
    Maven 环境的配置
    zTree的简单例子
    plsql免安装客户端的配置
    HDU 1232 畅通工程
    HDU 5698 瞬间移动
    Codeforces 1015E1 Stars Drawing (Easy Edition)
    Codeforces 784B Santa Claus and Keyboard Check
    Codeforces 500C New Year Book Reading
    NSarray 赋值 拷贝 等问题记录
    UINavigationController 操作记录
  • 原文地址:https://www.cnblogs.com/cicada-smile/p/11974550.html
Copyright © 2011-2022 走看看