1. 单一职责
就一个类而言,应该仅有一个引起它变化的原因。
如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭到意想不到的破坏。
软件设计真正要做的许多内容,就是发现职责并把那些职责互相分离。如果你多于一个动机去改变一个类,那么这个类就具有多于一个的职责。
2. 开放封闭
软件实体(类,模块,函数等)应该可以扩展,但是不可修改。也就是说,对于扩展是开放的,对于更改是封闭的。
如此设计,面对需求的改变可以保持相对的稳定,从而使系统可以在第一个版本以后不断的推出新的版本。
无论模块是多么的'封闭',都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。
等到变化发生时立即采取行动。
在我们最初编写代码时,假设变化不会发生。当变化发生时,我们就创建抽象来隔离以后发生的同类变化。
面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。
我们希望的是在开发工作展开不久就知道可能发生的变化。查明可能发生的变化所等待的时间越长,要创建正确的抽象就越困难。
开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护、可扩展、可复用、灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都可以的进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。
3. 依赖倒转
高层模块不应该依赖底层模块。两个都应该依赖抽象。
抽象不应该依赖细节,细节应该依赖抽象。
抽象不应该依赖细节,细节应该依赖于抽象,针对接口编程,不要对实现编程。
依赖倒转其实可以说是面向对象设计的标志,用哪种语言来写程序并不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程, 即程序中所有的依赖关系都终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。
4. 里氏代换
一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且察觉不出父类对象与子类对象的区别。也就是说,在软件里面,把父类都替换成它的子类,程序的行为没有变化。
子类型必须能用替换掉它们的父类型。
只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。
5. 合成/聚合复用
尽量使用合成/聚合,尽量不要使用类继承。
优先使用对象的合成/聚合将有助于你保持每个类被封装并被集中在单个任务上,这样累和类继承层次会保持较小的规模,并且不大可能增长为不可控制的庞然大物。
6. 迪米特法则
如果两个类不必彼此直接通信,那么着两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
在类的结构设计上,每一个类都应当尽量降低成员的访问权限,也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开。
迪米特法则其根本思想是强调了类之间的松耦合。
类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。
辅助资料:
常用创建型设计模式(其他类型模式就不提了,自己看书)
创建型模式隐藏了这些类的实例是如何被创建和放在一起,整个系统关于这些对象所知道的是由抽象类所定义的接口。这样,创建型模式在创建了什么、谁创建它=它是怎么被创建的,以及何时创建这些方面提供了很大的灵活性。
1. 工厂方法模式(Factory Method)
객체 생성을 위한 인터페이스를 정의하고 하위 클래스가 인스턴스화할 클래스를 결정하도록 합니다. 팩토리 패턴은 클래스의 하위 클래스 인스턴스화를 지연합니다.
생성 패턴은 인스턴스화 프로세스를 추상화하여 시스템이 객체가 생성, 구성 및 표현되는 방식에 독립적이도록 도와줍니다. 생성 패턴은 시스템이 사용하는 특정 클래스에 대한 정보를 캡슐화합니다. 고객은 구조와 기능이 매우 다양한 '제품' 개체로 시스템을 구성할 수 있습니다. 구성은 정적(즉, 컴파일 타임에 지정)이거나 동적(즉, 런타임에 지정)일 수 있습니다.
일반적으로 디자인은 팩토리 방식에서 시작해야 합니다. 디자이너가 더 큰 유연성이 필요하다고 판단하면 디자인은 다른 창작 패턴으로 발전합니다. 다양한 생성 패턴을 이해하면 설계자에게 설계 기준 간의 균형을 맞출 때 더 많은 옵션을 제공할 수 있습니다.
2. 추상 팩토리 패턴(Abstract Factory)
특정 클래스를 지정하지 않고 일련의 또는 관련된 종속 개체를 생성하기 위한 인터페이스를 제공합니다.
3. 빌더 모드(빌더)
복잡한 객체의 구성과 표현을 분리하여 동일한 구성 프로세스가 다른 표현을 만들 수 있습니다.
응집성과 결합 응집력은 루틴의 내부 구성요소가 얼마나 밀접하게 상호 연결되어 있는지를 나타냅니다. 결합은 루틴이 다른 루틴과 얼마나 밀접하게 연결되어 있는지를 설명합니다. 소프트웨어 개발의 목표는 내부적으로 완전한 루틴, 즉 응집력이 뛰어나고 다른 루틴과의 연결이 작고 직접적이며 가시적이며 유연한 루틴, 즉 느슨하게 결합되는 루틴을 만드는 것입니다.
복잡한 객체의 구성과 표현을 분리하여 제품의 내부 표현을 쉽게 변경하고 구성 코드를 표현 코드와 별도로 유지합니다. 이런 식으로 고객은 제품 제작 과정에 신경 쓸 필요가 없지만 고객이 필요한 것이 무엇인지 알려주기만 하면 동일한 제작 프로세스를 사용하여 고객을 위한 다양한 제품을 만들 수 있습니다.
4. 프로토타입
프로토타입 인스턴스를 사용하여 생성할 객체의 유형을 지정하고, 이러한 프로토타입을 복사하여 새 객체를 생성합니다.
여러 개의 종속 프로토타입을 생성하고 복제하는 것이 매번 적절한 상태로 클래스를 수동으로 인스턴스화하는 것보다 더 편리한 경우가 많습니다.
5. 싱글톤
클래스에 인스턴스가 하나만 있음을 보장하고 이에 대한 전역 액세스 지점을 제공합니다.
일부 수업의 경우 인스턴스가 매우 중요합니다. 전역 변수를 사용하면 개체에 액세스할 수 있지만 클라이언트가 여러 개체를 인스턴스화하는 것을 방지할 수는 없습니다. 싱글톤의 장점은 클래스 자체가 유일한 인스턴스를 저장한다는 것입니다. 이 클래스는 다른 인스턴스가 생성되지 않도록 보장하며, 싱글톤은 인스턴스에 액세스하는 메서드도 제공합니다. 이를 통해 클라이언트가 액세스하는 방법과 시기를 고유한 인스턴스에 대해 엄격하게 제어할 수 있습니다.