设计模式开篇

设计模式定义

设计模式是在某情境下,针对某问题的某种解决方案。
1.情境是应用某个模式场景;
2.问题是在某情境下达到的目标;
3.解决方案是以一个通用的设计,来解决约束、达到目标;

设计模式原则

设计模式的原则有六大原则,分别是单一职责原则里氏替换原则依赖倒置原则接口隔离原则迪米特法则开闭原则

1、单一职责原则

单一职责原则(Single Responsibility Principle)定义:应该有且仅有一个原因引起类的变更
一个类如果承担的职责越多,可复用性越小,可维护性越差。若过多的职责耦合在一个类中,容易牵一发动全身,影响其他职责的运行。因此,需要将职责分离,将相同职责的方法聚合在一个类中。
例如:下图是用户信息图,在同一个接口中包含用户的属性信息以及行为信息。
用户信息
运用单一职责原则,将接口重新拆分成2个接口,以此降低耦合性,IUserbehavior接口包含用户的行为信息,IUserAttribute接口包含用户的属性信息。
用户信息
单一职责原则的优点:
1.降低类的复杂性,实现类的职责都有明确的定义
2.提高类的可读性
3.提高类的可维护性
4.降低类变更引起的风险

2、里氏替换原则

里氏替换原则(Liskov Substitution Principle)有两种定义:
第一种定义:如果对每一个类型为 T1 的对象 o1,都有类型为 T2 的对象 o2,使得以 T1 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
第二种定义:所有引用基类的地方必须能透明地使用其子类的对象。

里氏替换通俗来说,就是子类可以替代父类调用,不会产生任何的错误和异常。反之,父类不可以替代子类的调用。就比如说啮齿动物是父类,老鼠是子类,啮齿动物能干的是,老鼠一定能干,而老鼠能干的事,啮齿动物不一定能干。
例:HavaFun类内重载了run方法,分别针对Dog类和Cat类
在这里插入图片描述
添加一个新的Animals类,Dog类和Cat类分别继承自Animals类,并实现各个特有的方法。根据里氏替换原则,HaveFun中的run方法可以实现Animals类,必然是可以实现Dog类和Cat类的。新的类图可以添加新的子类,而不用修改HavaFun内的run方法,降低耦合性。
在这里插入图片描述

3、依赖倒置原则

依赖倒置原则(Dependency Inversion Principle)定义:
抽象不应该依赖于细节,细节应依赖于抽象。简而言之,就是要针对接口编程,而不是针对实现编程。
例:一个Reader类内实现阅读小说的方法。
在这里插入图片描述
若Reader类内想要阅读文学经典,那必须在Reader类增加新的方法;若不再阅读小说,则需要删除public void read(Novel novel)方法。这种设计耦合性较高,不利于代码的维护和拓展。利用依赖倒置原则,将类图修改如下,创建两个接口,分别为IReader和IBook。实现IReader接口,可以创建不同的Reader类;实现IBook接口,可以创建不同的Book类。依赖倒置原则一般与里氏替换原则相互配合使用。
在这里插入图片描述
依赖是可以传递的,只要做到抽象依赖,即使多吃的依赖传递也无所畏惧
依赖的三种写法:
首先创建两个接口:

public interface IBook {
    public void show();
}
public interface IReader {
    public void read();
}

1.构造函数传递依赖对象

public class Reader implements IReader {
    private IBook book;

    public Reader(IBook book) {
        this.book = book;
    }

    @Override
    public void read() {
        book.show();
    }
}

2.Setter方法传递依赖对象

public class Reader implements IReader {
    private IBook book;

    public Reader() {
    }

    public void SetBook(IBook book) {
        this.book = book;
    }

    @Override
    public void read() {
        book.show();
    }
}

3.接口声明依赖对象
修改IReader接口:

public interface IReader {
    public void read(IBook book);
}
public class Reader implements IReader {
    
    @Override
    public void read(IBook book) {
        book.show();
    }
    
}

4、接口隔离原则

接口隔离原则(Interface Segregation Principle)有两种定义:
第一种定义:客户端不应该依赖它不需要的接口。
第二种定义:类间的依赖关系应该建立在最小的接口上。

以上两个定义通俗来讲,建立单一的接口,不要建立臃肿庞大的接口,尽量让接口细化。接口隔离原则与单一职责原则类似,但不一样,单一职责原则强调的是相同的职责放入一个接口内,比如一个接口内允许10个方法,10个方法可能包含5个模块。接口隔离原则强调按照模块来分离接口,尽量满足多个模块使用多个接口。
例:ISports接口里面有多种运动的方法。
在这里插入图片描述
依照接口隔离原则,对ISports接口按照模块进行细分,分成3个模块接口,分别为IPlayball接口、IAthletics接口、IWater接口。
在这里插入图片描述
根据接口隔离原则拆分接口时,必须首先满足单一职责原则

5、迪米特法则

迪米特法则(Low of Demeter)也叫做最少知识原则(Least Knowledge Principle)。通俗而言,一个类对自身需要耦合或者调用的类应该知道的最少,不管被调用的类内部如何复杂,调用者值只关心被调用者暴露出来的方法。
迪米特法则有几层含义:

1.只和朋友交流
意思指的是只和直接朋友通信。每个对象都必然会和其他对象有耦合关系,两个对象之间的耦合就成为朋友关系,这种关系比如有组合、聚合、依赖等。

2.朋友间也是有距离的
例:Client中的start方法调用Server类,方法内部分别调用Server类中的first方法、second方法、third方法。出现的问题是Server暴露的方法太多,耦合关系比较紧密
在这里插入图片描述
“朋友间也是有距离的”,尽量不要对外公布太多的方法和非静态的public变量,尽量使类内部比较内敛。修改类图如下,添加一个initial方法,在此方法内依次调用first方法、second方法、third方法。
在这里插入图片描述
3.是自己的就是自己的
有一些方法,放在本类中也可以,放在其他类中也没有错误,如何判定“是自己的就是自己的”呢?有一个原则:如果一个方法放在本类中,即不增加类间关系,也对本类不产生负面影响,就放置在本类中

6、开闭原则

开闭原则(Open-Closed Principle)的定义:一个软件实体应当对扩展开放,对修改关闭。软件实体可以指一个软件模块、一个由多个类组成的局部结构或一个独立的类。

开闭原则贯穿于以上五个设计模式原则。任何软件都需要面临一个问题,即软件的需求会随着时间的推移而改变。当软件面对新的需求时,应尽量保证系统框架的稳定性。若软件符合开闭原则,可以方便地对系统进行扩展,无须修改现有的代码,使代码具有适应性和灵活性的同时具备高稳定性。

设计模式分类

设计模式分为三大类:
1.创建型模式(5种):工厂方法模式抽象工厂模式单例模式建造者模式建造者模式原型模式
2.结构型模式(7种):适配器模式装饰器模式代理模式外观模式桥接器模式组合模式亨元模式
3.行为型模式(11种):策略模式模板方法模式观察者模式迭代器模式责任链模式命令模式备忘录模式状态模式访问者模式中介者模式解释器模式

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值