设计模式之禅-2 设计模式
23 种设计模式
1 单例模式
定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
实现:private 修饰构造方法,在本类中提供静态方法获取唯一的实例。
使用场景:在一个系统中,要求一个类有且只有一个对象,如果出现多个对象会有“不良反应”,则可以采用单例模式。
实际使用:工具类,spring默认生成的bean。
可能引入的问题:多线程环境下单例可能存在线程安全问题。
2 工厂方法模式
定义:定义一个用于创建对象的接口,让子类去决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
使用方式:
//抽象产品类 public abstract class Product { public abstract void method(); } //产品实现类A public abstract class ProductA extend Product { public void method(){ } } //产品实现类B public abstract class ProductB extend Product { public void method(){ } } //抽象工厂类 public abstract class Factory { public abstractextends Product> T create(Class c); } //抽象工厂类 public class ProductFactory extends Factory { public extends Product> T create(Class c){ Product p = (Product)Class.forName(c.getName()).newInstance(); return (T)p; } }
使用场景:工厂方法模式是new一个对象的替代品,所以在所有需要生成对象的地方都可以使用,但是要考虑成本,以及是否增加复杂度。当需要一个灵活、可扩展的框架时可以考虑使用。
扩展:
- 简单工厂模式:一个模块只需要一个工厂类,没必要生产出来,直接使用静态方法。
- 升级为多个工厂类:为每个产品定义一个工厂类,由使用者选择使用哪个工厂。
- 替代单例模式。
- 延迟初始化:一个对象被消费完毕后,并不直接释放,工厂类保持其初始化状态。缓存已创建对象,重复使用。
3 抽象工厂模式
定义:为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。
//抽象产品类phone public abstract class Phone { public abstract void phone(); } //产品实现类HWPhone public class HWPhone extend Phone { public void phone(){ } } //产品实现类MiPhone public class MiPhone extend Phone { public void phone(){ } } //抽象产品类PC public abstract class PC { public abstract void pc(); } //产品实现类HWPc public class HWPc extend PC { public void pc(){ } } //产品实现类MiPc public class MiPc extend PC { public void pc(){ } } //抽象工厂类 public abstract class AbstractCreator{ public abstract Phone phone(); public abstract PC pc(); } //产品等级1的实现类 public class HWCreator extends AbstractCreator { public abstract Phone phone(){ return new HWPhone(); } public abstract PC pc(){ return new HWPc(); } } //产品等级2的实现类 public class MiCreator extends AbstractCreator { public abstract Phone phone(){ return new MiPhone(); } public abstract PC pc(){ return new MiPc(); } } public static void main (String []args){ AbstractCreator crator = new HWCreator(); Phone phone = crator.phone(); Pc pc = crator.pc(); }
ps: 有N个产品族,在抽象工厂类中就因该有N个创建方法;有M个产品等级,就有M个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。
使用场景:一个对象族(或者一组没有任何关系的对象)有相同的约束,则可以使用抽象工厂模式。
缺点:产品族扩展非常困难。
4 模板方法模式
定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中。 使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。
模板模式仅使用了java的继承机制。其中AbstractClass叫做抽象模板,它的方法分为两类:
- 基本方法:是由子类实现的方法,并且在模板方法被调用。
- 模板方法:可以有几个,一般是一个具体的方法,也就是一个框架,实现对基本方法的调用,完成固定的逻辑。
ps:为防止恶意操作,一般模板方法中都加上final关键字,不允许被覆写。
public abstract class AbstractClass{ // 基本方法 public abstract void do someThing(); // 基本方法 public abstract void do anyThing(); // 模板方法 public void do templateMethod(){ this.someThing(); this.anyThing(); } }
使用场景:多个子类有公有的方法,并且逻辑相同
扩展:使用钩子方法,让子类的返回值决定公共部分的执行结构。
public abstract class AbstractClass{ // 基本方法 public abstract void doSomeThing(); // 基本方法 public abstract void doAnyThing(); // 模板方法 public void do templateMethod(){ this.doSomeThing(); if(select()){ this.doAnyThing(); } } // 钩子方法 protect abstract boolean select(); }
5 建造者模式
也称生成器模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
在建造者模式中,有四种角色:
- Product产品类,通常是实现了模板方法模式,也就是有模板方法跟基本方法。
- Builder抽象建造者,规范产品的组建,一般由子类实现。
- ConcreteBuilder 具体建造者,实现抽象类定义的所有方法,并且返回一个组建好的对象。
- Director 导演类,负责安排已有模块的顺序,然后告诉builder开始建造。
//产品类 public class Product{ } //抽象建造者 public abstract class Builder{ // 建造产品 public abstract Product builderProduct(); // 设置产品的不同部分,以获得不同的产品 public void setPart(); } //建造者实现类 public class concreteProduct extends Builer{ private Product product = new Product(); public void setPart(){ // 产品内部逻辑,修改product属性值 } public Product builderProduct(){ return product; } } //导演类 public class Director{ private Builder builder = new concreteProduct(); public Product getProductA(){ builder.setPart(); return builder.builderProduct(); } }
setPart()方法是零件的配置。什么是零件?其他的对象,获得一个不同零件,或者不同的装配顺序就可能产生不同的产品。
导演类的作用是封装,避免高层模块深入到建造者内部的实现类。
使用场景:
- 相同的方法,不同的执行顺序,产生不同事件结果。
- 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同。
- 建造者模式 vs 工厂模式: 建造者模式关注的是零件类型与装配顺序,工厂模式关注的是创建,创建零件是它的主要职责,组装顺序不是它关心的