前言

去年的11月份吧,我考下了中级软件设计师的证书,里面的必考题之一就是设计模式,虽然也没有很难考,但是如果你是要去国企工作的读者,其实我建议还是考上一考,一方面是对知识的复习,另一方面就是多少加一点工资。
以下附上一个报名的链接:http://bm.ruankao.org.cn/sign/welcome

思维导图

设计模式.png

六大原则

文章结构:定义 ---> 白话

单一职责原则

定义:就一个类而言,应该仅有一个引起它变化的原因。

其实字面意思就已经表达的比较明确,单一,也就是干尽量少的事情。在HDU中可以对耦合和内聚程度的评判有一定的了解。
什么叫做少,其实很难有一个标准。但是在Android的MVC框架中,Activity既作为View,又起着Controller的作用的时候是否显得会很臃肿呢?他需要进行页面的刷新,网络处理,消息处理等等,写起来容易,但是在我们进行维护的时候,是不是会很头疼呢。

开放封闭原则

定义:类,模块,函数等应该是可以扩展的,但是不可以修改。

在日常的项目开发中,需求一直是处于一个变动的状态,但是这同样也会成为项目开发的壁垒,如果你的Bean今天是一只猫,明天就需要是一只狗呢?重新打补丁吗?显然是一个很不合适的做法。而开放封闭原则,解决的就是这一类问题。不论是猫,还是狗,他们总会有相同的特征,抽象化也就是这个原则实现的基础。

// 定义一个动物抽象类
public abstract class Animal {
    abstract void do();
}

// 猫实现抽象方法
class Cat extends Animal {
    @Override
    void do() {
        System.out.println("喵");
    }
}

// 狗实现抽象方法
class Dog extends Animal {
    @Override
    void do() {
        System.out.println("汪");
    }
}

里氏替换原则

定义:所有引用基类(一般来说都是抽象类或接口)的地方必须能透明的使用其子类的对象。

定义的具体含义就是将一个基类对象替换成其子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。
或者你还是不理解的话,以下两段代码,就很清晰的解析了上述的含义。

List list = new ArrayList<String>();
ArrayList list = new List<String>();

ArrayList作为我们撸代码日子里的亲人,你见过第二种写法吗?
接下来就是里氏替换原则的具体实现了。

/**
 * 基于里氏替换原则实现
 */
class Manage1 {
    private Animal animal;

    public void setAnimal(Animal animal) {
        this.animal = animal;
    }

    void getSound() {
        animal.do();
    }
}

/**
 * 使用子类实现
 */
class Manage2 {
    private Cat cat;

    public void setAnimal(Cat cat) {
        this.cat = cat;
    }

    void getSound() {
        cat.do();
    }
}

以上基于两种写法,给予读者评判,如果使用Manage2,如果我们希望获得Dog的声音,那么就需要重新实现Manager3,然后差异就是只是把Cat置换成Dog。而Manage1很好的解决了这个问题,因为不论是Cat还是Dog都是Animal的子类。

依赖倒置原则

定义:高层模块不应该依赖底层模块,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。

两个概念:

  • 抽象/高层模块:接口或者抽象类,一般只定义了有什么操作,但是没有具体实现。
  • 细节/底层模块:实现接口或者继承抽象类而产生的,一般来说就是new出来的对象。

这里的代码与里氏替换原则一致。

迪米特原则

定义:一个软件实体应当少的与其他实体发生相互作用。

其实和上面的内容差不多,同样都是为了降低耦合程度,直接用Demo证明就清楚明了了。

电话网络形式

  • 打电话的人 --> 接电话的人
  • 打电话的人 --> 中间服务商转接 --> 接电话的人

第一种已经被时代抛弃了,虽然我们并不知觉,但是第一种电话网络模式,如果用在现代社会,那么带来的后果就是你再也看不见太阳了,头顶密密麻麻的电话线,更何况那是座机互联的时代,能够靠电话线来解决,但是这个时代呢?移动互联的时代呢,不能再靠着电话线来解决问题,而是中间商的介入就改变了这个现状。

第一种电话网络模式

/**
 * 打电话的人
 */
class Call {
    private Receiver receiver;

    public void setReceicer(Receiver receiver) {
        this.receiver = receiver;
    }

    public void call() {
        receiver.receive();
    }
}

/**
 * 接电话的人
 */
class  Receiver{

    private String number;
    Receiver(String number){
         this.number = number;
    }

    public void receive() {
        System.out.println("接通电话");
    }
}

class Main{
    public static void main(String[] args) {
        Call call = new Call();
        call.setReceicer(new Receiver("电话号码"));
        call.call();
    }
}

第二种电话网络模式

/**
 * 转接
 */
public abstract class Manager {
    abstract void link();
}

/**
 * 打电话的人
 */
class Call {
    private Manager manager;

    public void setManager(Manager manager) {
        this.manager = manager;
    }

    public void call() {
        manager.link();
    }
}

/**
 * 接电话的人
 */
class  Receiver{

    private String number;
    Receiver(String number){
         this.number = number;
    }

    public void receive() {
        System.out.println("接通电话");
    }
}

class CMCC extends Manager {
    private String number;

    CMCC(String number){
      this.number = number;
    }

    public void link() {
        System.out.println("连接接电话的人");
        Receiver receiver = new Receiver();
        receiver.receive();
    }
}

class Main{
    public static void main(String[] args) {
        Call call = new Call();
        call.setManager(new CMCC("电话号码"));
        call.call();
    }
}

这个时候两个实体通过加入中间商的形式降低了耦合度。

接口隔离原则

定义:一个类对另一个类的依赖应该建立在最小的接口上

一个接口内要实现的函数数量可控,有那么一点像数据库里的第一范式。让我们从Demo看看使用原则的与否的不同之处。

正常实现

// 特征
interface Character {
    void look();
    void nature();
}

class Dog implements Character{
    @Override
    void look() {
        System.out.println("能看");
    }
    @Override
    void nature() {
        System.out.println("淘气");
    }
}

基于接口隔离原则实现

// 外观
interface Facade {
     void look();
}
// 内在
interface Inherent {
    void nature();
}

class Dog implements Inherent{
    @Override
    void nature() {
        System.out.println("淘气");
    }
}

总结

七大原则其实表明的意思还是比较明确的,虽然可能写法上的难度会有一定的增加,但是如果使用得当,后期的维护成本将会大大降低。