1.5 接口隔离原则
1 接口隔离原则概念 接口隔离原则:客户端不应该依赖那些它不需要的接口。 当一个接口太大时,应该将它根据需要分割成多个更细小的接口,每个接口仅承担一个相对独立的角色或功能,使用该接口的客户端仅需知道与之相关的方法即可。 但是,接口不能过小,否则系统中接口太多,不利于维护。一般而言,在接口中仅包含为某一类用户定制的方法即可。
1.4 最少知识原则
1 最少知识原则(迪米特法则) 概念迪米特法则:每一个软件单位对其他单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位 迪米特法则要求一个软件实体应当尽可能少地与其他实体发生相互作用。如果一个系统复合迪米特法则,那么当修改其中某一个模块时就会尽量少地影响其他模块。应用迪米特法则可以降低系统的耦合度。在类的设计上应该注意以下几点:在类的划分上应尽量创建松耦合的类,类之间的耦合度越低,越有利于复用;类的结构设计上,每一个类都应该降低其成员变量和成员函数的访问权限。 2 实例于对象 O 中的一个方法 m ,m 方法仅能访问如下这些类型的对象: O 对象自身; m 方法的参数对象; 任何在 m 方法内创建的对象; O 对象直接依赖的对象; 具体点儿就是,对象应尽可能地避免调用由另一个方法返回的对象的方法。现代面向对象程序设计语言通常使用 “.” 作为访问标识,LoD 可以被简化为 “仅使用一个点(use only one dot)”。也就是说,代码 a.b.Method() 违反了 LoD,而 a.Method() 则符合 LoD。打个比方,人可以命令一条狗行走,但是...
1.6 合成复用原则
1 合成复用原则概念 合成复用原则:优先使用对象组合,而不是通过继承来达到复用的目的。 根据UML类图关系,合成复用原则指导在软件设计时,优先使用关联、聚合和组合关系,尽量少用泛化(继承)。对象组合可以使系统更加灵活(黑箱复用),降低类与类之间的耦合度,一个类的变化尽可能不影响其他类(父类和子类耦合度高不高?)。如果要使用继承,则需考虑里氏代换原则和依赖倒转原则。继承关系会破坏系统的封装性,会将基类的实现细节暴露给子类(白箱复用),如果基类发生改变,那么子类的实现也不得不改变。
1.7 依赖倒置原则
依赖倒转原则概念依赖倒转原则:高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。 什么是高层,什么是低层呢?它们指的是继承(派生)中的基类子类关系,基类或者越抽象的类,层次越高。简单说,依赖倒转原则要求针对接口编程,不要针对实现编程。 依赖倒转原则要求再程序代码中传递参数时,或在关联关系中,尽量引用层次高的出现层类,即使用接口或抽象类来声明变量类型、参数类型声明、方法返回类型声明,以及数据类型转换等,而不要使用具体类来做这些事情。(其实这一点也符合里氏代换原则的指导意义,即对一个方法而言,返回基类的地方一定可以返回子类)。同样,依赖倒转原则设计的关键也在与抽象化设计。
2.1 单例模式
单例模式Singleton1 概念意图保证一个类仅有一个实例,并提供一个访问它的全局访问点。 结构使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。 私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。 参与者Singleton 定义一个 Instance 操作,允许客户访问它的唯一实例。Instance 是一个类操作。 可能负责创建它自己的唯一实例。 适用性在以下情况下可以使用 Singleton 模式: 当类只能有一个实例并且客户可以从一个众所周知的访问点访问它时。 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。 缺点 系统检查开销。实现中可能每次都需要检查实例是否存在,这个问题可以通过 Static 实例来解决。 系统资源开销。通常 Singleton 中的对象一旦被创建,不会被及时销毁。可以通过提供 Reset 操作来重置。 引起开发混淆。如果类包括 public 构造函数可以在外部构造,当使用 Singleton 对象时,开发人员需要记住不能使用...
2.3 工厂方法
工厂方法别名 虚构造器 (Virtual Constructor) 意图 定义一个用于创建目标对象的接口,让子类决定实例化哪一个目标类。Factory Method 使一个类的实例化延迟到其子类。 Define an interface for creating an object, but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses. 结构 参与者 Product 定义工厂方法所创建的对象的接口(Interface)。 ConcreteProduct 实现 Product 接口。 Creator 声明工厂方法,该方法返回一个 Product 类型的对象。 Creator也可以定义一个工厂方法的缺省实现,它返回一个缺省的 ConcreteProduct 对象。 可以调用工厂方法以创建一个 Product 对象。 ConcreteCreator 重定义(Override)工厂方法以创...
2.6 原型模式
原型模式别名 Clone 意图 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 Specify the kinds of objects to create using a prototypical instance, and createnew objects by copying this prototype. 结构 参与者 Prototype 声明一个克隆自身的接口。 ConcretePrototype 实现一个克隆自身的操作。 Client 让一个原型克隆自身从而创建一个新的对象。 适用性 在以下情况下可以使用 Prototype 模式: 一个系统要独立于它的产品的创建、构成和表示时。 当要实例化的类是在运行时刻指定时,例如:通过动态装载。 为了避免创建一个与产品类层次平行的工厂类层次时。 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。 缺点 每一个 Prototype 子类都必须实现 Clone操作。当内部包括一些不支持拷贝或有循环引用的对象时...
3.1 适配器
适配器模式别名 包装器(Wrapper) 意图 将一个类的接口转换成客户希望的另外一个接口。 Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。结构 类适配器使用多重继承对一个接口与另一个接口进行匹配。 对象适配器依赖于对象组合。 参与者 Target 定义 Client 使用的与特定领域相关的接口。 Client 与符合 Target 接口的对象协同。 Adaptee 定义一个已经存在的接口,这个接口需要适配。 Adapter 对 Adaptee 的接口与 Target 接口进行适配。 适用性 在以下情况下可以使用 Adapter 模式: 你想使用一个已经存在的类,而它的接口不符合你的需求。 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作。 你想使用一些已经存在的类,但是不可能对每一个都进行子类化匹配它们的接口。对象适配器可以适配它的父类的接口。 效果 允许一个 Adapter 与多个 Adaptee (Adaptee 本身及它的子类)同时协同。Adapter也可以一次给所有的 Adapt...
3.5 外观
意图 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 Provide a unified interface to a set of interfaces in a subsystem. Facadedefines a higher-level interface that makes the subsystem easier to use. 结构 参与者 Facade 知道哪些子系统类负责处理请求。 将客户的请求代理给适当的子系统对象。 Subsystem Classes 实现子系统的功能。 处理由 Facade 对象指派的任务。 没有 Facade 的任何相关信息。 适用性 在以下情况下可以使用 Facade 模式: 当你要为一个复杂子系统提供一个简单接口时。 客户程序与抽象类的实现部分之间存在着很大的依赖性。 当你需要构建一个层次结构的子系统时,使用 Facade模式定义子系统中每层的入口点。 效果 它对客户屏蔽子系统组件,使用 Facade 的客户程序不需要直接访问子系统对象。...
3.6 享元
享元模式意图 运用共享技术有效地支持大量细粒度的对象。 Use sharing to support large numbers of fine-grained objects efficiently. 结构 下面的对象图说明了如何共享 Flyweight: 参与者 Flyweight 描述一个接口,通过这个接口 Flyweight 可以接受并作用于外部状态。 ConcreteFlyweight 实现 Flyweight接口,并为内部状态增加存储空间。该对象必须是可共享的。它所存储的状态必须是内部的,即必须独立于对象的场景。 UnsharedConcreteFlyweight 并非所有的 Flyweight 子类都需要被共享。Flyweight接口使共享成为可能,但它并不强制共享。 FlyweightFactory 创建并管理 Flyweight 对象。 确保合理地共享 Flyweight。 Client 维持一个对 Flyweight 的引用。 计算或存储 Flyweight 的外部状态。 适用性 Flyweight 模式的有效性很大程度上取决于...














