一、六大设计原则
1、单一职责
一个方法尽可能做一件事情
单一职责原则(Single Responsibility Principle,SRP)
2、接口隔离原则
尽量依赖最小的接口
3、依赖倒置原则:
高层模块不应该依赖低层模块(基础模块),两者都应该依赖其抽象,传递的是抽象
抽象不应该依赖细节
细节应该依赖抽象
4、里氏替换原则
继承必须确保超类所拥有的性质在子类中仍然成立(其阐述了有关继承的一些原则)
5、开闭原则
一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)
6、迪米特法则
一个对象应该对其他对象有最少的了解,所以迪米特法则又叫做最少知识原则
二、23种设计模式(GOF)
设计模式可分为三种类型,创建型模式、结构型模式和行为型模式
创建型模式(5种)
- 抽象工厂模式(Abstract Factory)
- 建造者模式(Builder)
- 工厂方法模式(Factory Method)
- 原型模式(Prototype)
- 单例模式(Singleton)
单例模式
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例
简单工厂、工厂方法模式、抽象工厂模式
简单工厂模式
// 简单工厂核心类 class ShapeFactory { public static Shape createShape(String des) { switch (des) { case "t": return new Triggle(); case "c": return new Circle(); case "r": return new Rectangle(); } return null; } }
由一个工厂对象(ShapeFactory中createShape方法)决定创建出哪一种产品类的实例。
工厂方法模式
//日志记录器工厂接口:抽象工厂LogFactory abstract class LogFactory { public abstract Log createLog(); } //文件日志记录器工厂类:具体工厂FileLogFactory class FileLogFactory extends LogFactory { @Override public Log createLog() { System.out.println("使用文件工厂"); return new FileLog(); } } //数据库日志记录器工厂类:具体工厂DatabaseLogFactory class DatabaseLogFactory extends LogFactory { @Override public Log createLog() { System.out.println("使用数据库工厂"); return new DatabaseLog(); } }
工厂方法模式把简单工厂进行了拆分,由原来根据条件集中创建,分散到创建工厂子类(FileLogFactory、DatabaseLogFactory)中进行创建。把对象的实例化推迟到子类。
抽象工厂模式
//数据库工厂接口:抽象工厂DBFactory interface DBFactory{ public Connection createConnection(); public Statement createStatement(); } //Oracle数据库工厂:具体工厂OracleFactory class OracleFactory implements DBFactory{ @Override public Connection createConnection() { return new OracleConnection(); } @Override public Statement createStatement() { return new OracleStatement(); } } //MySQL数据库工厂:具体工厂MySQLFactory class MySQLFactory implements DBFactory{ @Override public Connection createConnection() { return new MySQLConnection(); } @Override public Statement createStatement() { return new MySQLStatement(); } } //客户端测试类 public class lab1_3 { public static void main(String[] args) { try { DBFactory factory; Connection connection; Statement statement; factory = new MySQLFactory(); connection = factory.createConnection(); connection.connect(); statement = factory.createStatement(); statement.state(); } catch (Exception e) { System.out.println(e.getMessage()); } } }
抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。其创建不再是一个对象,而是一组相关或相互依赖的对象(OracleFactory、MySQLFactory)。
抽象工厂模式-Abstract Factory Pattern
原型模式
在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与Java融为一体,大家可以随手拿来使用。
建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
四个角色:Product(产品角色),Builder(抽象建造者),ConcreteBuilder(具体建造者),Director(指挥者)
建造者模式适用场景 :
- 结构复杂 : 对象 有 非常复杂的内部结构 , 有很多属性 ;当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。
- 分离创建和使用 : 想把 复杂对象 的 创建 和 使用 分离 ;
【设计模式】建造者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
StringBuilder构建String的一个示例:
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence { public StringBuilder() { super(16); } public java.lang.StringBuilder append(Object obj) { return append(String.valueOf(obj)); } public java.lang.StringBuilder append(String str) { super.append(str); return this; } public java.lang.StringBuilder append(boolean b) { super.append(b); return this; } public java.lang.StringBuilder append(char c) { super.append(c); return this; } public java.lang.StringBuilder append(int i) { super.append(i); return this; } // ... 其它操作字符串的实现 public String toString() { return new String(value, 0, count); } }
结构型模式(7种)
- 适配器模式(Adapter)
- 桥接模式(Bridge)
- 组合模式(Composite)
- 装饰模式(Decorator)
- 外观模式(Facade)
- 享元模式(Flyweight)
- 代理模式(Proxy)
适配器模式
将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。
适配器角色:
- 目标角色(target):这是客户锁期待的接口。目标可以是具体的或抽象的类,也可以是接口
- 适配者角色(adaptee):已有接口,但是和客户器期待的接口不兼容。
- 适配器角色(adapter):将已有接口转换成目标接口。定义默认实现,使用时只实现需要的接口
适配器模式有分三类:
- 类适配器模式(class adapter pattern),adapter extends adaptee implements target
- 对象适配器模式(object adapter pattern),adapter implements target,并且包含adaptee
- 缺省适配器模式(default adapter pattern),也叫默认适配器模式、接口适配器模式
优点(总结): 类适配器模式(class adapter pattern):
由于适配器adapter类是适配者adaptee类的子类,因此可以在适配器类中置换一些适配者的方法,即Override(重写),使得适配器的灵活性更强。
对象适配器模式(object adapter pattern):
一个对象适配器可以把多个不同的适配者adaptee适配到一个目标,也就是说,同一个适配器可以将适配者类和它的子类都适配到目标接口。
桥接模式
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
主要角色:
- 抽象化(Abstraction)角色:定义抽象类,并包含一个对实现化对象的引用。提供高层控制逻辑, 依赖于完成底层实际工作的实现对象。
- 扩展抽象化(Refined Abstraction)角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化(Implementor)角色:定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化(Concrete Implementor)角色:给出实现化角色接口的具体实现。
- 客户端(Client):仅关心如何与抽象部分合作。但是,客户端需要将抽象对象与一个实现对象连接起来。
适用场景:
- 当一个对象有多个变化因素的时候,考虑依赖于抽象的实现,而不是具体的实现。如手机品牌有2种变化因素,一个是品牌,一个是功能。
- 当多个变化因素在多个对象间共享时,考虑将这部分变化的部分抽象出来再聚合/合成进来,如通讯录和游戏,其实是可以共享的。
- 当我们考虑一个对象的多个变化因素可以动态变化的时候,考虑使用桥接模式,如上面例子中的手机品牌是变化的,手机的功能也是变化的,所以将他们分离出来,独立的变化。
装饰模式
动态地给一个对象添加一些额外的功能,比生成子类要灵活。
使用场景:
需要透明且动态地拓展类的功能的场景。
角色:
- 抽象组件Component类。
- 组件具体实现ConcreteComponent类。也是被装饰的对象。
- 抽象装饰类Decorator,内部持有一个组件对象的引用,职责就是装饰ConcreteComponent类。之所以是抽象的,就是为了方便不同的装饰“风格”子类的自定义实现。
- 具体装饰类ConcreteDecorator。
装饰模式总结:
装饰模式动态地给一个对象添加一些额外的功能,相对于继承的方式,更加灵活。
装饰模式经常被误认为是代理模式。装饰模式是以对客户透明的方式扩展对象的功能,是继承关系的一个替代方案。而代理模式则是给一个对象提供一个代理对象,并由代理对象来控制原有对象的引用。
前者重在增加功能,后者重在对代理对象施加控制,不是对对象本身功能的增强。
// FilterInputStream 装饰类,InputStream 为抽象组件 public class FilterInputStream extends InputStream { protected volatile InputStream in; // ... }
组合模式
组合模式又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。
使用场景:
当你发现需求中是用树形结构体现部分与整体层次关系的结构时,且你希望用户可以忽略整体和部分、组合对象和单个对象的不同,统一地使用组合结构中的所有对象时,就应该使用组合模式。
组合模式解决上面所说的两个问题:
1、部分与整体的层次关系表示为树形结构、
2、部分与整体的对象,是能让客户端能统一对待、不需区分的对象。
场景:树形菜单,文件、件夹的管文理。
角色
组合模式有三个基本部件: 即抽象部件、叶子部件、树枝部件,这三个部件组成的一颗树形结构。
- 抽象构件(Component):叶子构件和容器构件继承的抽象类,包含叶子和容器的共有行为的声明,如业务方法,也可能包含管理叶子的方法。
- 叶子构件(Leaf):树的叶结点,实现抽象构件的业务方法,对于容器特有的管理子结点的方法,可以使用空方法或者抛出异常处理。
- 树枝构件(Composite):树的叶结点,实现抽象构件的业务方法,对于容器特有的管理子结点的方法,可以使用空方法或者抛出异常处理。
组合模式的两种分类
组合模式根据代码实现的不同分为透明组合模式和安全组合模式