【设计模式七大原则及Java示例】


CSDN博客地址 https://blog.csdn.net/weixin_47053123
Github项目下载地址https://github.com/MaBo2420935619


设计模式七大原则

UML图中,绿线标识继承或者实现,白线表示依赖关系
原则并不是孤立存在的,它们相互依赖,相互补充。
在这里插入图片描述

单一职能原则

单一职责原则(Single Responsibility Principle) SRP

单一职责原则好处

  • 降低类的复杂性 每个类实现单一职责,并且单一职责都有清楚明确的定义,复杂性当然降低。
  • 提高可读性
    类的复杂性降低了,当然提高了可读性了。
  • 提高可维护性
    类的复杂性降低,可读性好,当然好维护。
  • 提高扩展性
    通俗点的话来说就是一个类只干一件事,或者一个方法只干一件事。

代码这里不再做过多的演示

接口隔离原则

客户端不应该依赖它不需要的接口
类间的依赖关系应该建立在最小的接口上

利用马,和鱼的例子还说名。
马需要吃饭和走路
鱼需要吃饭和游动
设计的实现接口如下
在这里插入图片描述

/**
 * @Author mabo
 * @Description   接口隔离原则
 */
public class InterfaceIsolation {
    //吃
    interface Eat{
        public void eat();
    }
    //走路
    interface Walk{
        public void walk();
    }
    //游动
    interface Swim {
        public void swim();
    }

    //马在吃和走路
    class Horse implements Eat , Walk{

        @Override
        public void eat() {
            System.out.println("马在吃");
        }

        @Override
        public void walk() {
            System.out.println("马在走");
        }
    }
    //鱼在吃和游
    class Fish implements Eat ,Swim{
        @Override
        public void eat() {
            System.out.println("鱼在吃");
        }

        @Override
        public void swim() {
            System.out.println("鱼在游");
        }
    }
}

倒转置换原则

依赖倒转(倒置)的中心思想是面向接口编程
依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在java中,抽象指的是接口或抽象类,细节就是具体的实现类
使用接口或抽象类的目的是:制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
倒转置换可以有三种写法

这里用小猫小狗跑来做示例
在这里插入图片描述

1.接口作为方法参数
在这里插入图片描述

/**
 * @Author mabo
 * @Description 依赖倒转
 * @Description 方法接口作为参数
 */
public class DependencyInversion1 {
    private interface Animal {
        public void run();
    }

    private static class Action {
        public void go(Animal animal) {
            animal.run();
        }
    }

    private static class Dog implements Animal {
        @Override
        public void run() {
            System.out.println("小狗在跑");
        }
    }

    private static class Cat implements Animal {
        @Override
        public void run() {
            System.out.println("猫在跑");
        }
    }


    public static void main(String[] args) {
        Action action = new Action();
        action.go(new Dog());
        action.go(new Cat());
    }
}

2.接口作为属性,利用构造方法初始化接口
在这里插入图片描述


/**
 * @Author mabo
 * @Description     依赖倒转
 * @Description     类参数为接口
 */
public class DependencyInversion2 {
    private interface Animal{
        public void run();
    }

    private static class Action{
        private Animal animal;
        /**
         * @Author mabo
         * @Description   通过构造方法传入接口
         */
        public Action(Animal animal) {
            this.animal=animal;
        }
        public void go() {
            animal.run();
        }
    }
    private static class Dog implements Animal {
        @Override
        public void run() {
            System.out.println("小狗在跑");
        }
    }
    private static class Cat implements Animal {
        @Override
        public void run() {
            System.out.println("猫在跑");
        }
    }

    public static void main(String[] args) {
     Action dogAction=new Action(new Dog());
     dogAction.go();
     Action catAction=new Action(new Cat());
     catAction.go();
    }
}

3.接口作为属性,利用set方法初始化接口
在这里插入图片描述


/**
 * @Author mabo
 * @Description     依赖倒转
 * @Description     setter方法传入接口
 */
public class DependencyInversion3 {
    private interface Animal{
        public void run();
    }

    private static class Action{
        private Animal animal;

        public void setAnimal(Animal animal) {
            this.animal = animal;
        }
        //通过构造方法传入接口
        public void go() {
            animal.run();
        }
    }
    private static class Dog implements Animal {
        @Override
        public void run() {
            System.out.println("小狗在跑");
        }
    }
    private static class Cat implements Animal {
        @Override
        public void run() {
            System.out.println("猫在跑");
        }
    }

    public static void main(String[] args) {
        Action dogAction=new Action();
        dogAction.setAnimal(new Dog());
        dogAction.go();
        Action catAction=new Action();
        catAction.setAnimal(new Cat());
        catAction.go();
    }
}

里氏替换原则

里氏替换原则的主要作用

  • 里氏替换原则是实现开闭原则的重要方式之一。
  • 它克服了继承中重写父类造成的可复用性变差的缺点。
  • 它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
  • 加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性、可扩展性,降低需求变更时引入的风险。

里氏替换原则的定义可以总结如下:

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
  • 子类中可以增加自己特有的方法
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入参数)要比父类的方法更宽松
  • 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的的输出/返回值)要比父类的方法更严格或相等
    在这里插入图片描述
    这里用燕子和麻雀继承鸟做说明
/**
 * @Author mabo
 * @Description   里氏置换原则
 */
public class RichterSubstitutionPrinciple {
    public static void main(String[] args) {
        Bird bird1 = new Swallow();
        Bird bird2 = new Sparrow();
        bird1.setSpeed(120);
        bird2.setSpeed(120);
        System.out.println("如果飞行300公里:");
        try {
            System.out.println("燕子将飞行" + bird1.getFlyTime(300) + "小时.");
            System.out.println("几维鸟将飞行" + bird2.getFlyTime(300) + "小时。");
        } catch (Exception err) {
            System.out.println("发生错误了!");
        }
    }
    //鸟类
    public static class Bird {
        double flySpeed;
        public void setSpeed(double speed) {
            flySpeed = speed;
        }
        public double getFlyTime(double distance) {
            return (distance / flySpeed);
        }
    }
    //燕子类
    public static class Swallow extends Bird {
    }
    //麻雀
    public static class Sparrow extends Bird {
        //不应该重写父类方法
//        public void setSpeed(double speed) {
//            flySpeed = 0;
//        }
       public  void getFar(double distance){
           System.out.println(distance);
       }
    }
}


合成/聚合复用原则

合成复用原则(Composite Reuse Principle,CRP)又叫组合/聚合复用原则(Composition/Aggregate Reuse Principle,CARP)
简单理解合成复用就是将现有对象作为当前类的成员变量,开发中很常见

开闭原则

开闭原则

  • 类的改动是通过增加代码进行的,不是修改源代码。
  • 抽象化是开闭原则的关键。

在这里插入图片描述

这里用三角形和圆继承图像来说明

/**
 * @Author mabo
 * @Description   开闭原则
 */
public class OpenClosePrinciple {
    static abstract class Sharp{
        public abstract void paint();
    }
     static class DrawingEditor{
        public void draw(Sharp sharp){
            sharp.paint();
        }
    }

    static class Rectangle extends Sharp{

        @Override
        public void paint() {
            System.out.println("画一个矩形");
        }
    }
     static class Circle extends Sharp{

        @Override
        public void paint() {
            System.out.println("画一个圆形");
        }
    }

    public static void main(String[] args) {
        DrawingEditor drawingEditor=new DrawingEditor();
        drawingEditor.draw(new Circle());
        drawingEditor.draw(new Rectangle());
    }

}

迪米特法则

迪米特法则又叫做最少知道原则,就是说一个对象应当对其它对象有尽可能少的了解,不要和陌生人说话。
强调只和朋友说话,不和陌生人说话。这里的朋友指的是:出现在成员变量,方法输入,输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于朋友类
迪米特法则初衷在于降低类之间的耦合。由于每个类尽量减少对其它类的依赖,因此。很容易使得系统的功能模块独立,相互之间不存在(或很少有)依赖关系。
错误的例子

/**
 * @Author mabo
 * @Description   迪米特法则
 * @Description   直接朋友 要求依赖的类是成员变量,方法参数,方法返回值
 * @Description   最好将自己依赖的类作为成员变量,叫做类之间是朋友关系
 * @Description   对自己依赖的类,最好直接调用类的方法,而不是将类作为局部变量
 */
public class DemeterBadExample {
    private static class Student{
        private List list=new ArrayList();
        public List getList() {
            return list;
        }
        public void setList(List list) {
            this.list = list;
        }
        public void addList(){
            list.add(1);
        }
    }

    public static void main(String[] args) {
        Student student=new Student();
        student.addList();
        List list = student.getList();
        int size = list.size();
        System.out.println(size);
    }
}

正确写法

/**
 * @Author mabo
 * @Description   迪米特法则
 * @Description   直接朋友 要求依赖的类是成员变量,方法参数,方法返回值
 * @Description   最好将自己依赖的类作为成员变量,叫做类之间是朋友关系
 * @Description   对自己依赖的类,最好直接调用类的方法,而不是将类作为局部变量
 */
public class DemeterPrinciple {
    //将需要依赖的类作为成员变量
    private static Student student=new Student();

    private static class Student{
        private List list=new ArrayList();

        public List getList() {
            return list;
        }

        public void setList(List list) {
            this.list = list;
        }

        public void addList(){
            list.add(1);
        }
        public int size(){
            return list.size();
        }
    }

    public static void main(String[] args) {
        student.addList();
//        List list = student.getList();
//        int size = list.size();

        int size = student.size();
        System.out.println(size);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值