「设计原则二」

「设计原则二」

一、单一职责原则

单一功能职责,一个类应该有且仅有一个引起它变化的原因,也即一个类只负责一项职责。不仅仅是类,实际开发过程中,方法的的处理也是遵循尽可能处理单一的功能,否则应该考虑将它们进行拆分。

  • 如果在设计时不遵循单一职责原则,一个类或者方法承载了多个功能,那么某一个职责变化时,有可能影响其他职责的变化,导致系统的不可控。
  • 破坏单一职责原则,系统可读性、可维护性都会降低;造成大量代码冗余。
1.作用
  • 降低了类或方法的复杂度。(由于粒度小,派生的类难免会增加,但同保持系统的稳定比,这点牺牲是值得的)。
  • 职责清晰,提高了系统的可读性、可维护性。
  • 对系统变更的适应能力更强,单一的职责修改对其他的职责影响很小。
2.实际问题

设计一个邮件接收系统,实际生活中,我们可以一个邮箱绑定多个其他厂商的邮箱账号,统一管理。

  • 无非就是连接对应的邮箱提供厂商的系统,拉取邮件到客户端,自然地能想到如下接口设计:
/**
 * Created by Sai
 * on: 06/01/2022 16:24.
 * Description:
 */
public interface EmailProvider {
  void makeClient();
  void downloadEmails();
  void disConnectFromService();
}
//定义了三个方法,连接服务器,拉取最新邮件,断开连接;很明显的违背了单一职责原则。
//在这个接口中我们只想它的操作仅仅执行下载任务,连接的协议是可变的。可以是QQ邮箱、Gmail等
  • 修改后的接口
/**
 * Created by Sai
 * on: 06/01/2022 16:24.
 * Description:
 */
public interface EmailProvider {
  void downloadEmails();
}
  • 提供Client连接类管理连接,支持各种连接协议
/**
 * Created by Sai
 * on: 06/01/2022 16:24.
 * Description:
 */
public class EmailClient {
  private final List<EmailProvider> providers = new CopyOnWriteArrayList<>();

  //EmailProvider 接口作为传参,面向接口
  public void addProvider(EmailProvider provider) {
    providers.add(provider);
  }

  public void downloadEmails() {
    for (var provider : providers) provider.downloadEmails();
  }
}
  • 实现QQ邮箱连接类
/**
 * Created by Sai
 * on: 06/01/2022 16:24.
 * Description:
 */
public class QQMailClient {

    public void makeClient() {
        System.out.println("Connect to Tencent Mail Services...");
    }

    public void fetchFreshMails() {
        System.out.println("Fetch fresh Mails...");
    }

    public void disConnectFromService() {
        System.out.println("Disconnect from the services...");
    }
}
  • QQ邮箱具体连接与加载类
/**
 * Created by Sai
 * on: 06/01/2022 16:24.
 * Description:
 */
public class QQMailAdapter implements EmailProvider {

    private final QQMailClient client = new QQMailClient();

    @Override
    public void downloadEmails() {
        client.makeClient();
        client.fetchFreshMails();
        client.disConnectFromService();
    }
}
  • 实现Gmail连接类
/**
 * Created by Sai
 * on: 06/01/2022 16:24.
 * Description:
 */
public class GmailClient  {
  public void connect() {
    System.out.println("Connecting to Gmail");
  }

  public void getEmails() {
    System.out.println("Downloading emails from Gmail");
  }

  public void disconnect() {
    System.out.println("Disconnecting from Gmail");
  }
}
  • Gmail具体连接加载类
/**
 * Created by Sai
 * on: 06/01/2022 16:24.
 * Description:
 */
public class GmailAdapter implements EmailProvider {
    private final GmailClient client = new GmailClient();

    @Override
    public void downloadEmails() {
        client.connect();
        client.getEmails();
        client.disconnect();
    }
}
  • 客户端测试类
/**
 * Created by Sai
 * on: 06/01/2022 16:24.
 * Description:
 */
public class Demo {
  public static void show() {
    var client = new EmailClient();
    client.addProvider(new GmailAdapter());
    client.addProvider(new QQMailAdapter());
    client.downloadEmails();
  }

  public static void main(String[] args) {
    show();
  }
}


Connecting to Gmail
Downloading emails from Gmail
Disconnecting from Gmail
----------------------
Connect to Tencent Mail Services...
Fetch fresh Mails...
Disconnect from the services...
----------------------

Process finished with exit code 0
3. 思考
  • 设计的原则不应该停留在记忆里,更不是死记硬背,思考加灵活运用到实际问题当中才能更加深刻的理解然后变成自己的东西,这个简单的例子遵循了单一职责原则、依赖倒置原则,当然也是最简单的适配器模式(Adapter Design Patterns)
二、接口隔离原则

一个类不应该依赖它不需要使用的方法(接口),通俗的讲,一个类对另一个类的依赖应该建立在最小的接口之上。单一职责原则同样也规定了单一功能的重要性,可以发现这些设计原则本身都相互关联的。

1.作用
  • 分解臃肿庞大的接口(接口承担的职责太多)为多个粒度更小的接口(提高可维护性、灵活性,Java接口的多实现单继承)。

  • 提高了系统的内聚性,降低了耦合,减少了对外交互。

  • 减少冗余代码(实现了本不需要的方法),结构清晰,提高了可维护性。

2.拆分原则
  • 接口隔离粒度是需要仔细细考的,一味的追求小接口数量过多,系统复杂度会显著提升,相反的粒度太大同样达不到降低灵活性的目的。这就要求开发者对业务的抽象能力以及全局思考的能力。一个接口一个模块或者一个子系统。
  • 提高内聚,以最少的方法做最多的事情。
  • 定制化接口,泛化出接口屏蔽系统不需要的方法,保留仅仅需要的最小方法数(接口基类配置)。
三、迪米特法则

"不跟陌生人说话",设计过程中总是要遵循高内聚、低耦合,各个模块之间只有耦合尽可能低,才能够提高代码的复用性,可读性。结构层次也更加清晰,迪米特法则的另一层含义:只与直接朋友交谈,如果系统之间无需之间通信,则不应该直接发生调用,而应该烦通过第三方(中介)调用,这样自然降低了系统的耦合程度,增强了相对独立性。

1.作用
  • 类与类之间尽量不直接通信(中介),降低了系统之间的耦合程度,增强了模块的独立性。
  • 低耦合度,提高了系统的可复用性、可扩展性。

同接口隔离一样,“粒度”问题还是需要注意,如果滥用迪米特法则,则会产生大量的“中介类”,系统复杂度反而提高了,项目同样会变得冗余,无论遵循什么样的原则,本质追求的就是使系统高内聚、低耦合,这个才是前提。

2.实现原则
  • 降低类成员的访问权限。
  • 只暴露该暴露的对外方法,尽可能用少的方法做更多的事情。
  • 只依赖应该需要依赖的类,避免实现不必要的空方法。
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,270评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,489评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,630评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,906评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,928评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,718评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,442评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,345评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,802评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,984评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,117评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,810评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,462评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,011评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,139评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,377评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,060评论 2 355

推荐阅读更多精彩内容