大话设计模式(序)

249 阅读5分钟

什么是设计模式?

在软件工程中,软件设计模式是针对软件设计中给定上下文中常见问题的通用可重用解决方案。这不是可以直接转换为源代码或机器代码的最终设计。它是关于如何解决可以在许多不同情况下使用的问题的描述或模板。设计模式是形式化的最佳实践,程序员可以在设计应用程序或系统时用来解决常见问题。
——————维基百科

为什么要用设计模式?

因为在开发中,软件设计是复杂又困难的,设计面向对象软件比较困难,设计可复用的面向对象的软件更是难上加难。

设计模式是一个“前人栽树,后人乘凉”的产物,“先辈”工程师从自身“踩过的坑,趟过的雷”中吸取经验,把开发中一些高效的模式,在特定场合可以发挥出色效果的多种方法集合起来,产生了设计模式,促进了软件工程化。

其中最重要的几点体现就是使用设计模式提升了代码的“可复用性、灵活性",使得其更加的“模块化、易于理解”。

一个模式的四个重要要素

  1. 模式名称:帮助记忆名字,理解具体意思;
  2. 问题:描述应该在何时被使用,需要解决什么样的问题;
  3. 解决方案:如何去做,设计是由哪些组成的。其内部的相互关系与各自职责。
  4. 用了这个模式后会产生什么样的效果与影响。

面向对象的几个基本原则:

大家学了这么久的面向对象,可能还不了解为何要如此的设计,在此我们来讲解下,在设计模式中无论多么的复杂、难以理解的东西,都逃不过“SOLID”原则。

什么是SOLID原则

简单总结一下就是:

  • [S] The Single Responsibility Principle 单一责任原则
  • [O] The Open Closed Principle 开放封闭原则
  • [L] Liskov Substitution Principle 里氏替换原则
  • [I] The Interface Segregation Principle 接口分离原则
  • [D] The Dependency Inversion Principle 依赖倒置原则

[S] The Single Responsibility Principle 单一责任原则

那么,单一责任原则是什么呢?

其定义为:一个类只能承担一种责任。

也就是让一个类只能做一类事,如果承担更多的工作,那么就分解这个类。

例如:

public class Dog {
    private String name;
    private int age;

    private void run(){
        System.out.println("I'm running");
    }
}
//一个Dog类内只能承担和Dog相关的事情


public class Bird {
    private String name;
    private int age;

    private void fly(){
        System.out.println("I'm flying");
    }
}
//一个Bird类只能承担和bird相关的事情

[O] The Open Closed Principle 开放封闭原则

其定义为:实体应该对扩展是开放的,对修改是封闭的。

也就是类应该无需修改类本身,但却比较容易扩展。

例如:

public class Dog {
    private String name;
    private int age;
    
    private void eat(){
        System.out.println("I eat meat");
    }
    
}
//每只Dog 都有名字和年龄。都喜欢吃肉。


public class Bird {
    private String name;
    private int age;

    private void eat(){
        System.out.println("I eat worm");
    }

}
//每只Bird 都有名字和年龄。都喜欢吃虫子。

那么这样是不是太麻烦了,我们可以利用开放封闭原则进行扩展:

public class Animal {
    private String name ;
    private int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println("I'm eating");
    }
}
//我们创建一个动物类,包含名字和年龄,一个吃的方法。


public class Dog extends Animal{

    public Dog(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("I eat meat");
    }
}
//然后我们继承Animal类,获得方法。并在原有基础上进行扩展,得到Dog。

public class Bird extends Animal {

    public Bird(String name, int age) {
        super(name, age);
    }

    @Override
    public void eat() {
        System.out.println("I eat worm");
    }
}
//然后我们继承Animal类,获得方法。并在原有基础上进行扩展,得到Bird。

[L] Liskov Substitution Principle 里氏替换原则

其定义为:一个对象在其出现的任何地方,都可以用子类实例做替换 也就是当子类可以在任意地方替换基类且软件功能不收影响时,不会导致程序的错误。 例如一些基本的JDK自带的collection集合类一样,你永远可以这样写:

    Map<String,String> map   = new HashMap<>();
    Map<String,String> map1  = new LinkedHashMap<>();
    Map<String,String> map2  = new TreeMap<>();
    
    
    

这就是里氏替换原则。

[I] The Interface Segregation Principle 接口分离原则

其定义为:多个专门接口比使用单一的总体接口要好,客户不应被强迫依赖它不使用的方法。 也就是一个类实现的接口中,包含了它不需要的方法。将接口拆分成更小和更具体的接口,有助于解耦,从而更容易重构与更改。

[D] The Dependency Inversion Principle 依赖倒置原则

其定义为:高层次的模块不应依赖低层次的模块,他们都应该依赖于抽象。抽象不应依赖具体实现,具体实现应依赖抽象。

依赖倒置是实现开闭原则的方法。

其中典型的例子就是IOC和DI,其功能实现了简单的语义化,你只需要告诉他你需要做什么,就会得到你想要的结果,这就是简单的依赖倒置。

总结

讲了这么多,其实这主要就是我们整天念叨的面向对象三大特性,“封装、继承、多态”。只是我们不知从何而来得出的。此篇文章就给大家讲解了一下具体来源,如有不正之处,望路大神予以纠正(逃

下一次我们来讲类的各种依赖关系,和如何画类图