设计模式零零碎碎知识点
1,设计模式的两大主题:系统复用,系统扩展
2,设计模式一般用来解决同一问题不同表相的问题
3,软件模型是软件开发工程师与软件分析设计师之间的桥梁
4,设计模式分为为:创建型模式,行为型模式,结构型模式
设计模式UML图
设计模式六大原则
- 单一职责:一个类只负责一个相应的职责,只会有一个原因会引起类的改动
- 开闭原则:一个类对扩展开放,对修改关闭,在添加更新功能时不修改源代码,多多使用接口和抽象类
- 里氏替换原则:所有引用基类的地方,必须可以使用其子类
- 依赖倒置原则:高层模块不应该依赖于底层模块,而是应该依赖于他们的抽象,编程要面向对象而不是面向过程
- 接口隔离原则:应该使用多个接口去替代总的接口
- 迪米特法则:不和陌生人讲话,一个类应该尽可能少的和其他类进行接触
设计模-式23个模式:
- 工厂模式
意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
缺点:违反了开闭原则,如果有新的类生成,则需要修改源代码
修改方法:将原本工厂模式的switch语句改换为类反射来创建类
- 抽象工厂模式
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类,一个工厂可以创建多个类别的类。
- 单例模式
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
缺点:无法被继承,因为构造方法是private
几种创建方法(参考菜鸟教程)
饿汉式:
描述:类加载即初始化
优点:未加锁,效率高,保证线程安全
缺点:类加载即创建,浪费资源
代码:
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
懒汉式/无线程安全:
描述:最基本最基础的单例模式创建,在被调用时才进行初始化
缺点:缺乏线程安全
懒汉式/线程安全:
描述:基于传统的懒汉模式,利用synchronized进行加锁
缺点:效率低下,大多数情况下不需要加锁
代码:
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
双检锁/双重校验锁
描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
优点:不对方法加锁,而是在内部使用双加锁机制,来判断单例是否被创建,大大提高了单例的性能
代码:
public class Singleton { private volatile static Singleton singleton; private Singleton (){} public static Singleton getSingleton() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
登记式/静态内部类
描述:利用静态内部类,达到延迟加载单例的效果,与饿汉式不同的是,饿汉式是类被装载即初始化,而登记式则是类被装载时不初始化,当你的静态内部类被访问时才进行初始化,同时也保证了线程安全
代码:
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
- 责任链模式
描述:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
- 中介者模式
描述:采用迪米特法则,用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
实例:所有用户沟通不是直接沟通,而是把自己要说的话发到聊天室里面进行信息传递
- 策略模式
描述:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换
- 适配器模式
描述:将两个毫不关联了的类,进行适配转换,将类A的信息转换为类B的模式
实例:我国采用的220v电压,国外采用110v电压,需要把中国的电器带到国外使用,需要使用电压转换器(适配器)来进行转换
缺点:
① 过多的使用适配器类会导致代码变得十分紊乱。
② 因为java继承只能为一个的原因,一个适配器只能实现一个适配类。
代码:
Target接口
public interface Target { //这是源类Adapteee没有的方法 public void Request(); }
源类(Adaptee 需要被适配的类)
public class Adaptee { public void SpecificRequest(){ } }
适配器类
//适配器Adapter继承自Adaptee,同时又实现了目标(Target)接口。 public class Adapter extends Adaptee implements Target { //目标接口要求调用Request()这个方法名,但源类Adaptee没有方法Request() //因此适配器补充上这个方法名 //但实际上Request()只是调用源类Adaptee的SpecificRequest()方法的内容 //所以适配器只是将SpecificRequest()方法作了一层封装,封装成Target可以调用的Request()而已 @Override public void Request() { this.SpecificRequest(); } }
- 外观模式
描述:让客户端可以访问系统端的一个接口,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
优点:
1、减少系统相互依赖。
2、提高灵活性。
3、提高了安全性。
缺点:不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
- 桥接模式
描述:将抽象部分与实现部分分离,使它们都可以独立地变化。在抽象类中放入接口实例。
- 建造者模式
意图:将一个个简单的类对象构造成一个复杂的组合,且相同的构建过程可以创造出不同的组合
优点:易扩展,具有独立性,大大减少构造方法
缺点: 产品必须有共同点,范围有限制。 如内部变化复杂,会有很多的建造类
- 命令模式
意图:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。
实例:计算机是接受命令者,使用者是发出命令的人,将每一个按键包装成一个命令,发送给计算机
优点:符合开闭原则,且可以进行撤回,返回操作,无需对原本的类本身进行修改
缺点:使用命令模式可能会导致某些系统有过多的具体命令类
- 迭代器模式
描述:将聚合类中的遍历方式分离开来,在保证内部结构不暴露的同时,让外部代码能透明的遍历获取聚合类中的数据
优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
public class NameRepository implements Container { public String[] names = {"Robert" , "John" ,"Julie" , "Lora"}; @Override public Iterator getIterator() { return new NameIterator(); } private class NameIterator implements Iterator { int index; @Override public boolean hasNext() { if(index < names.length){ return true; } return false; } @Override public Object next() { if(this.hasNext()){ return names[index++]; } return null; } } }
- 状态模式
意图:允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
优点: 1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点:
1、状态模式的使用必然会增加系统类和对象的个数。
2、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。
- 组合模式
意图:将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
优点:
1,结构清晰,高层模块调用简单
2,节点自由增加
缺点:
不符合依赖倒置原则全部都是以类的形式表达
- 模板方法模式
描述:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。(就是继承没啥好说的)
注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。