单例模式
定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
通用源码:
public class Singleton {
private static final Singleton singleton = new Singleton();
private Singleton(){
}
//通过该方法获得实例对象
public static Singleton getSingleton(){
return singleton;
}
//类中其他方法尽量是static
public static void doSomething(){
}
}
优点:
1. 在内存中只有一个实例,减少了内存开支。
2. 当一个对象的产生需要比较多的资源时,如读取配置、产生其它依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。
使用场景:
1. 要求生成唯一序列号的环境。
2. 在整个项目中需要一个共享访问点或共享数据,例如一个web页面上的计数器。
注意事项:
线程不安全的问题,可以在getSingleton方法前加synchronized关键字,也可以在getSingleton方法内增加synchronized来解决。
模板方法模式
定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
通用源码:
public abstract class AbstractClass {
//基本方法
protected abstract void doSomething();
//基本方法
protected abstract void doAnything();
//模板方法
public void templateMethod(){
this.doAnything();
this.doSomething();
}
}
public class ConcreteClass1 extends AbstractClass {
protected void doAnything() {
//业务逻辑处理
}
protected void doSomething() {
//业务逻辑处理
}
}
public class ConcreteClass2 extends AbstractClass {
protected void doAnything() {
//
}
protected void doSomething() {
}
}
public class Client {
public static void main(String[] args) {
AbstractClass class1 = new ConcreteClass1();
AbstractClass class2 = new ConcreteClass2();
class1.templateMethod();
class2.templateMethod();
}
}
优点:
1. 封边不变部分,封装可变部分。
2. 提取公共代码
3. 行为由父类控制,子类实现。
使用场景:
1. 多个子类共有的方法,并且逻辑基本相同时。
2. 重复复杂的算法,可以把核心算法设计成模板方法。周边的相关细节功能则由各个子类实现。
3. 重构时,模板方法是一个经常使用的模式,把相同的代码抽到父类中,然后通过钩子函数约束其行为。
建造者模式
定义:将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示。
通用类图:
角色如下:
1. Product产品类:通常是实现了模板方法模式,也就是有模板方法和基本方法。
2. Builder抽象建造者:规范产品的组建。
3. ConcreteBuilder具体建造者:实现抽象类定义的所有方法,并且返回一个组装好的对象。
4. Director导演类:负责安排已有模块的顺序,然后告诉Builder开始建造。
通用源码:
public class Product{
public void doSomething(){
//业务处理
}
}
public abstract class Builder{
//设置产品的不同部分,以获得不同的产品
public abstract void setPart();
//建造产品
public abstract Product buildProduct();
}
public class ConcreteProduct extends Builder {
private Product product = new Product();
//设置产品零件
public void setPart(){
/*
* 产品类内的逻辑处理
*/
}
//组建产品
public Product buildProduct() {
return product;
}
}
public class Director {
private Builder builder = new ConcreteProduct();
public Product getAProduct(){
builder.setPart();
/*
* 设置不同的零件,产生不同的产品
*/
return builder.buildProduct();
}
}
优点:
1. 封装性好。客户端不必知道产品内部组成的细节。
2. 建造者独立,容易扩展。
3. 便于控制细节风险。由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。
使用场景:
1. 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。
2.多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同时可以使用。
3. 产品类非常复杂或者产品类中的调用顺序不同产生了不同的效能。
4. 在对象创建过程会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到。
最佳实践:
建造者模式最主要的功能时基本方法的调用顺序安排,通俗的说就是零件的装配,顺序不同产生的对象也不同。而工厂方法则重点是创建,创建零件是它的主要职责,组装顺序则不是他关心的。在使用建造者模式时可以考虑下模板方法模式,别孤立的思考一个模式。