我是靠谱客的博主 合适玉米,最近开发中收集的这篇文章主要介绍设计原则(单一职能原则,开闭原则,里氏替换原则,依赖倒置原则,接口分离原则,迪米特原则),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

面向对象思想设计原则

在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设计原则

单一职能原则

开闭原则

里氏替换原则

依赖倒置原则

接口分离原则

迪米特原则


1.单一职能原则

单一职责原则
其实就是开发人员经常说的”高内聚,低耦合”
也就是说,每个类或每个方法都只负责一件事情。
在设计模式中,所有的设计模式都遵循这一原则

public class postive {
    
    public static StringBuilder loadFile(String fileLocation) throws IOException {
      
            //读取文件的内容
            Reader in = new FileReader("E:\1.txt");
            BufferedReader bufferedReader = new BufferedReader(in);

            String line = null;
            StringBuilder sb = new StringBuilder("");

            while ((line = bufferedReader.readLine()) != null) {
                sb.append(line);
                sb.append(" ");
            }
            
            bufferedReader.close();
            return sb;
    }
    
    public static String[] getWords(String regex, StringBuilder sb){
        //对内容进行分割
        return  sb.toString().split(regex);
    }
    
    public static void main(String[] args) throws IOException {
        
            //读取文件的内容
            StringBuilder sb = loadFile("E:\1.txt");
            
            //对内容进行分割
            String[] words = getWords("[^a-zA-Z]+", sb);
            
            System.out.println(words.length);
    }
}

遵守单一原则,可以给我们带来的好处是,提高了代码的可重用性,同时还让得到的数据不再有耦合,可以用来完成我们的个性化需求。


2.开闭原则

开闭原则

核心思想是:一个对象对扩展开放,对修改关闭。

其实开闭原则的意思就是:对类的改动是通过增加代码进行的,而不是修改现有代码。

也就是说软件开发人员一旦写出了可以运行的代码,就不应该去改动它,而是要保证它能一直运行下去,如何能够做到这一点呢?这就需要借助于抽象和多态,即把可能变化的内容抽象出来,从而使抽象的部分是相对稳定的,而具体的实现则是可以改变和扩展的。

定义一个Car类:

public class Car {
    private String name;
    private String color;
    private float price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }
}

开闭原则不能在源代码上修改,定义一个DaZheCar类,继承Car类,重写setPrice方法:

public class DaZheCar extends Car {
    @Override
    public void setPrice(float price) {
        super.setPrice(price*0.8F);
    }
}

测试类:

public class MyTest {
    public static void main(String[] args) {
        Car car = new DaZheCar();
        car.setName("宝马");
        car.setColor("白色");
        car.setPrice(666666F);

        float price = car.getPrice();
        System.out.println(price);
    }
}


3. 接口隔离原则

核心思想:不应该强迫程序依赖它们不需要使用的方法。

其实就是说:一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该把所有的操作都封装到一个接口中。

一个接口中有多种方法,例如,鸟会飞,会跳,会跑等等:

public interface MyInterface {
    void jump();
    void fly();
    void swimming();
    void running();
}

而要实现的只是鸟会飞这个功能,如果实现上面的接口,就得重写所有方法,所有我们只定义一个鸟会飞的接口:

public interface FlyInterface {
    void fly();
}

通过测试类去实现这个接口,从而达到只想要鸟会飞这个功能:

public class Bird implements FlyInterface {

    @Override
    public void fly() {
        System.out.println("学会了飞");
    }
}


4.依赖倒置原则

上层不能依赖于下层。

他们都应该依赖于抽象。

反例:

class Person {
    public void feed(Dog dog) {
        System.out.println("开始喂养");
        dog.eat();
    }
}

class Dog {
    public void eat() {
        System.out.println("狗吃骨头");
    }
}

public class MyTest {
    public static void main(String[] args) {
        Person person = new Person();
        Dog dog = new Dog();
        person.feed(dog);
    }
}

什么是上层,什么是下层?

调用别的方法的,就是上层,被其他方法调用的就是下层。

也就是说MyTest类中的 main方法中调用Person中的 feed(dog); 方法,那么MyTest类是上层 Perso类就是下层

Person和Dog Person中调用了Dog中的eat()方法,那么Person就是上层,Dog就是下层

现有有一个需求:需要增加一个猫类喂养:

那么我们在定义一个猫类
class Cat {
    public void eat() {
        System.out.println("猫吃小鱼干");
    }
}

那么就又需要在Person类中提供一个重载方法:

class Person {
    public void feed(Dog dog) {
        System.out.println("开始喂养");
        dog.eat();
    }

    public void feed(Cat cat) {
        System.out.println("开始喂养");
        cat.eat();
    }
}
public class MyTest {
    public static void main(String[] args) {
        Person person = new Person();
        Dog dog = new Dog();
        Cat cat = new Cat();
        person.feed(dog);
        person.feed(cat);
    }
}

也就是说,我每增加一个动物,都需要在Person类中提供一个重载方法

那现在就是 上层依赖于下层 也就是Person类 依赖于Dog类,Cat 类

那么下层每增加一个类,就得去修改上层,违反了依赖倒置,也就是下层一变化,上层也跟着变。

我们希望的是,当下层增加一个类时,上层应该不知道,也就是上层不应该发生变动。

正例:

class Person {
    public void feed(Animal an) {
        System.out.println("开始喂养");
        an.eat();
    }
}
abstract class Animal{
    public abstract void eat();
}
class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}

class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃小鱼干");
    }
}

public class MyTest {
    public static void main(String[] args) {
        Person person = new Person();
        Dog dog = new Dog();
        Cat cat = new Cat();
        person.feed(dog);
        person.feed(cat);
    }
}

现在我们的上层Person只依赖于Animal

下层的改动,不在影响上层


5.迪米特原则(最少知道原则)

核心思想:一个类应当对其他类知道的越少越好。

只和朋友通信。

什么是朋友?

1.类中的字段是朋友

2.方法的参数是朋友

3.方法的返回值是朋友

4.方法中实例化出来的对象是朋友

定义一个电脑类,这个类中有关机的多种操作方法,而我们需要把这个方法都统一写到另一个方法中:

class Computer {
    private void saveData() {
        System.out.println("保存数据...");
    }

    private void killProcess() {
        System.out.println("关闭程序");
    }

    private void closeScreen() {
        System.out.println("关闭屏幕");
    }

    private void powerOff() {
        System.out.println("关闭电源");
    }
    public void guanji(){
        this.saveData();
        this.killProcess();
        this.closeScreen();
        this.powerOff();
    }
}

 

定义一个人类,这个类要去进行关机操作时,只需要调用电脑类中的一个关机方法,而不需要调用多个关机操作的方法:

class Person {
    Computer computer = new Computer(); //朋友
    public void shutdown() {
       computer.guanji();
    }

    public void eat(StringBuffer sb) {
        String s = new String();
        computer.guanji();
    }
}

测试类,只需要调用人类中的关机方法,而人类中的关机方法又调用了电脑类中的关机方法:

public class MyTest {
    public static void main(String[] args) {
        Person person = new Person();
        person.shutdown();
    }
}


6. 里氏替换原则

里氏替换原则

核心思想:在任何父类出现的地方都可以用它的子类来替代。

其实就是说:子类可以随时随地替换父类对象,且替换完之后,语法不会报错,业务逻辑也不会出现问题。

需求:将长方形的宽改成比长大 1

我们先看正常情况下
class Rectangular {
    private Integer width; //宽
    private Integer length; //长

    public Integer getWidth() {
        return width;
    }

    public void setWidth(Integer width) {
        this.width = width;
    }

    public Integer getLength() {
        return length;
    }

    public void setLength(Integer length) {
        this.length = length;
    }

    //计算面积的方法
    public double getArea() {
        return length * width;
    }
}

//定义一个正方形的类,继承长方形
class Square extends Rectangular {
    private Integer sideWidth;//边长

    @Override
    public Integer getWidth() {
        return sideWidth;
    }

    @Override
    public void setWidth(Integer width) {
        this.sideWidth = width;
    }

    @Override
    public Integer getLength() {
        return sideWidth;
    }

    @Override
    public void setLength(Integer length) {
        this.sideWidth = length;
    }

    @Override
    public double getArea() {
        return sideWidth * sideWidth;
    }
}

public class MyTest {
    public static void main(String[] args) {
        Rectangular rectangular = new Rectangular();
        //这里可以替换成子类
                    rectangular = new Square();
        rectangular.setWidth(20);
        rectangular.setLength(15);
        double area = rectangular.getArea();
        System.out.println(area);
        System.out.println("==============================");
    }
}

特殊情况:

我再定义一个类
class Utils {
    public static void transform(Rectangular graph) {
        //如果宽小于等于长,就让宽加1
        while (graph.getWidth() <= graph.getLength()) {
            graph.setWidth(graph.getWidth() + 1);
            System.out.println("长:" + graph.getLength() + " : " +
                    "宽:" + graph.getWidth());
        }
    }
}
public class MyTest {
    public static void main(String[] args) {
        Rectangular rectangular = new Rectangular();
        //这里可以替换成子类,
        //rectangular = new Square();
        rectangular.setWidth(20);
        rectangular.setLength(150);
        System.out.println("==============================");
        //传入长方形的对象,没有问题,但是传入正方形就有问题了,成死循环了。
        Utils.transform(rectangular);
    }
}

//这里父类就不能用子类对象来替换了,替换之后,会发生问题

要知道,在向上转型的时候,方法的调用只和new的对象有关,才会造成不同的结果。在使用场景下,需要考虑替换后业务逻辑是否受影响。

由此引出里氏替换原则的使用需要考虑的条件:

    是否有is-a关系
    子类可以扩展父类的功能,但是不能改变父类原有的功能。

这样的反例还有很多,如:鸵鸟非鸟,还有咱们老祖宗早就说过的的春秋战国时期--白马非马说,都是一个道理。

最后

以上就是合适玉米为你收集整理的设计原则(单一职能原则,开闭原则,里氏替换原则,依赖倒置原则,接口分离原则,迪米特原则)的全部内容,希望文章能够帮你解决设计原则(单一职能原则,开闭原则,里氏替换原则,依赖倒置原则,接口分离原则,迪米特原则)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部