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

    摘自:https://www.cnblogs.com/cicada-smile/p/11974550.html

    软件工程六大设计原则总结,案例演示

     

    本文源码: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

     
  • 相关阅读:
    php生成二维码的几种方式
    CVPR 2013
    面试&笔试---c语言之字符串处理
    逆向知识-汇编寻址方式汇总
    tensorflow中的lstm的state
    图文相关性 flickr数据实验结论_1
    LightGBM中GBDT的实现
    Tensorflow 变量的共享
    Tensorflow 变量的共享
    https://github.com/chenghuige/tensorflow-exp/blob/master/examples/sparse-tensor-classification/
  • 原文地址:https://www.cnblogs.com/xichji/p/11981545.html
Copyright © 2011-2022 走看看