1.设计模式:
- 创建型模式(创建对象的同时隐藏创建逻辑,使得程序在判断针对某个给定实例需要创建哪些对象更加灵活):
- 工厂模式
- 抽象工厂模式
- 单例模式
- 建造者模式
- 原型模式
- 结构型模式(关注类和对象的组合):
- 适配器模式
- 桥接模式
- 过滤器模式
- 组合模式
- 装饰器模式
- 外观模式
- 享元模式
- 代理模式
- 行为型模式(关注对象之间的通信):
- 责任链模式
- 命令模式
- 解释器模式
- 迭代模式
- 中介者模式
2.创建型模式
- 工厂模式:定义一个用于创建对象的接口,让子类决定将创建哪一个类实例化。
- 缺点:
- 工厂类集中了所有的创建逻辑,一旦这个类出问题了,那么整个系统都要受到影响。
- 系统扩展困难,一旦添加新的产品就不得不修改工厂逻辑。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。
- 缺点:
- 抽象工厂方法:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体类别。是围绕一个超级工厂创建其他的工厂,,该超级工厂又称为其他工厂的工厂。
- 优点:
- 抽象工厂模式隔离了具体类的生成,使得客户并不知道什么被创建。
- 增加新的具体的工厂和产品族很方便,无须修改已有的系统,符合开闭原则。
- 当一个产品族被设计成一起工作时,它能够保证客户端始终只使用同一个产品族的对象。
- 缺点:
- 添加新的产品对象时,难以扩展抽象工厂来生产新种类产品。如果修改了抽象工厂类,就要对所有子类进行修改,将会带来不便。
- 优点:
- 建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
- 优点:
- 将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 每一个具体建造者都相对独立,而与其他的具体的建造者无关,因此可以很方便换具体建造者或者增加新的具体建造者。
- 缺点:
- 建造者模式所创建的产品一般具有较多相同点,如果产品之间的差异性大,则不适合建造者模式。
- 如果产品内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
- 优点:
- 原型模式:用原型实例指定创建对象的种类,并且通过复制这个原型来创建新的对象。需要考虑深克隆和浅克隆的问题。
- 深克隆:所有普通成员都含有与原来对象相同的值,除去那些引用其他对象的变量。那些引用其对象的变量将指向被复制过的的新对象。
- 浅克隆:仅仅复制所考虑的对象,而不复制它所引用的成员对象。所有的对其他对象等的引用仍然指向原来的对象。
- 优点:
- 当创建新的对象实例较为复杂,使用原型模式可以简化对象的创建过程,通过一个已有实例可以提高新实例的创建效率。
- 可以动态增加或减少产品类。由于创建产品类实例的方法是产品类内部具有的,因此增加新的产品对整个结构没有影响。
- 使用深克隆1可以保存对象状态。
- 缺点:
- 需要为每一个类配备一个克隆方法,而且这个克隆方法需要对类的功能进行考虑。如果需要对原有的类进行改造,违背了开闭原则。
- 实现深克隆需要实现复杂的代码。
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式要点有三个,一是某个类只能有一个实例,二是它必须自行创建这个实例,三是它必须自行向整个系统提供这个实例。单例模式考虑线程安全性
- 优点:
- 提供了对唯一实例的受控访问。
- 由于系统内存中只存在一个对象,可以节省系统资源。
- 允许可变数目的实例。
- 缺点:
- 由于单例模式没有抽象层,因此单例模式的扩展比较困难。
- 单例类的职责过重,在一定程度上违背了单一职责原则。单例类即充当了工厂角色,又充当了产品角色。
关于是否线程安全:
- 懒汉式:第一次调用才初始化,避免内存浪费。 必须加锁 synchronized 才能保证单例,但加锁会影响效率。
//赖汉式也分为线程安全和线程不安全两种 /* 线程不安全 ,因为没有加锁synchronized,所以也不是单例模式*/ public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } } /*线程安全*/ public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
- 饿汉式:是多线程安全的。没有加锁,执行效率会提高。类加载时就初始化,浪费内存。
- 双检锁/双重校验锁:是多线程安全的。这种方式采用双锁方式,安全且能保证高性能。
- 优点:
3.结构型模式
适配器模式:适配器模式是作为两个不兼容接口之间的桥梁,它结合了两个独立接口的功能。 意图:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于不兼容而不能一起工作的那些类可以一起工作。
这个模式由主要三个角色:目标抽象类(一般是抽象类或者接口),适配器类,适配者类- 优点:
- 将目标类和适配者类解耦
- 增加了类的透明性和复用性。
- 灵活性和扩展性都非常好
- 缺点:
- 对于Java和C#等不支持多重继承的语言,一次最多只能适配一个适配者类。
- 举例:
- 优点:
public interface Robot{
public void cry();
public void move();
}
class Dog{
public void wang(){
System.out.println("wang wang wang");
}
public void run(){
System.out.println("run run run");
}
}
class DogAdapter extends Dog implements Robots{
public void cry(){
System.out.println("robot");
super.wang();
}
public void move(){
System.out.println("robot");
super.run();
}
}
- 桥接模式:将抽象部分和实现部分分离,使他们都可以独立的变化。
- 优点:
- 分离抽象接口及其实现部分。
- 桥接模式有些类似于多继承,但是多继承违背了类的单一职责原则。
- 桥接模式提高了系统的可扩性,在两个变化维度中任意扩展一个维度,都不需要修改原有的系统。
- 缺点:
- 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,开发者需要对抽象层进行设计与编程。
- 桥接模式要求正确识别出系统两个独立变化的维度,因此使用有一定局限性。
- 举例:
- 优点:
public interface Color{
public void bepaint(String penType,String name);
}
class Red implements Color{
public void bepaint(String penType,String name){
System.out.println(penType+" 红色的"+name+" .");
}
}
class Yellow implements Color{
public void bepaint(String penType,String name){
System.out.println(penType+" 黄色的"+name+" .");
}
}
public abstract class Pen{
Protected Color color;
public void setColor(Color color){
this.color = color;
}
}
class BigPen extends Pen{
public void draw(String name){
String penType = "大号毛笔";
this.color.bepaint(penType,name);
}
}
class SmallPen extends Pen{
public void draw(String name){
String penType = "小号毛笔";
this.color.bepaint(penType,name);
}
}
- 组合模式:组合多个对象形成树形结构以表示“整体-部分”的结构层次。
- 优点:
- 组合模式可以清楚的定义分层次的复杂对象,表示对象的全部或者部分层次,使得增加构件变得容易。
- 客户端调用简单,客户端可以一致地使用组合结构或其中单个对象,用户不必关心自己处理的是单个对象还是整个组合结构。
- 缺点:
- 使对象变得抽象,对象的业务规则如果很复杂,则实现组合模式具有很大的挑战性。
- 举例:
- 优点:
public abstract class MyElement{
public abstract void eat();
}
class Apple extends MyElement{
public void eat(){
System.out.println("吃苹果");
}
}
class Pear extends MyElement{
public void eat(){
System.out.println("吃梨子");
}
}
public class Plate extends MyElement{
private ArrayList list = new ArrayList();
public void add(MyElement element){
list.add(element);
}
public void remove(MyElement element){
list.remove(element);
}
public void eat(){
for(Object object:list){ /*递归*/
((MyElement)object).eat();
}
}
}
4.行为型模式