前言
去年的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("淘气");
}
}
总结
七大原则其实表明的意思还是比较明确的,虽然可能写法上的难度会有一定的增加,但是如果使用得当,后期的维护成本将会大大降低。
以上就是我的学习成果,如果有什么我没有思考到的地方或是文章内存在错误,欢迎与我分享。
相关文章推荐:
聊一聊设计模式(二)-- 创建型设计模式
聊一聊设计模式(三)-- 结构型设计模式
聊一聊设计模式(四)-- 行为型设计模式
网友评论