一、 单例模式
官方定义:Ensure a class has only onstance , and provide a gobal point of access to it.(确保毛一个类只有一个实例,而且自行实例化并向整个系统提供这个实例)
通俗说:在古代,一个国家只能有一个皇帝,皇帝每天要上朝接待臣子、处理政务,但皇帝是唯一的,我们就只有将构造函数设置为private私有反复权限,从而禁止外部创建对象了。一般分为两个类,一个是Emperor(皇帝类),一个是Minnister(臣子类)。
public class Emperor {
private static final Emperor emperor=new Emperor(); //初始化
private Emperor() {}
public static Emperor getInstance(){
return emperor;
}
public static void say(){
System.out.println("我是XXX……");
}
}
优点:①单例模式只有在内存中只有一个实例,减少了内存开支;
②减少了系统的性能开销,如当一个对象的产生需要较多的资源时,就可以优先考录单例模式;
③可以避免对资源的重复占用;
④可以设置全局访问点,优化和共享资源
缺点:①一般没有接口,扩展很难,一般都得修改代码;
②对测试不利;
③与单一职责原则有冲突
使用场景:①在整个项目只能中需要一个共享访问点或共享数据;
②创建对象需要消耗过的资源和需要定义大量的静态常量与方法时
注意事项(线程不安全):在系统压力增大时,当一个线程A执行到singleton=new Singleton() ,但没有获得对象,第二个线程B也在执行,执行到 singleton=null,那么线程B获得为真的判断,于是继续执行下去,线程A和B将都会获得一个对象,内存中就会出现两个对象。
解决办法:在getSingleton方法前加synchronized关键字。
public class Singleton {
private static final Singleton singleton = null;
private Singleton() {
}
public static Singleton getSingleton() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
二、工厂模式
官方定义:Define an interfae for creating an object , but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个雷的实例化延迟到其子类)。
在工厂模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义;Creator为抽象创建类,也就是抽象工厂,具体入市创建产品类是由具体的实现工厂ConcreteCreator完成的。
//抽象产品类
public abstract class Product{
//产品的公共方法
public void method1(){
}
//抽象方法
public abstract void method2();
}
//具体产品类
public class ConcreteProduct extends Product{
public void method2(){
}
}
//抽象工厂类
public abstract class Creator{
//创建一个产品对象
public abstract <T extends Product> T createProduct(Class<T> c) ;
}
//具体工厂类
public abstract class ConcreteCreator extends Creator{
public <T extends Product> T createProduct(Class<T> c){
Product product=null;
try{
product=(Product)Class.forName(c.getName()).newInstance();
}catch(Exception ef){
//异常处理
}
return (T)product;
}
}
//场景类
public class Client{
public static void main(String[] args ){
Creator creator=new ConcreteCreator();
Product product=new creator.createProduct(ConcreteProduct1.class);
}
}
优点:①良好的封装性,代码结构清晰;
②扩展性很好,在增加产品类时,只要适当的修改具体的工程类或扩展一个工程类;
③屏蔽产品类,产品的具体实现,调用者是不会关心的,他们只会在意产品的接口,只要接口未变就行了
使用场景:①是new 一个对象的代替品,所以在虽有需要生成对象的地方都可以使用;
②需要灵活的、可扩展的框架时
三、模板方法模式
,
官方定义:Define the skeleton of an algoriam in an operation , deferring some steps to subclasses .Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.(定义一个操作的算法的框架,而将一些步骤延迟到子类中。使得子类可以不变一个算法的结构即可重定义该算法的某些特定步骤)
模板方法模式使用了java的继承机制,是一个应用广泛的模式。它的方法分为两类:
基本方法:是由子类实现的方法,并且在模板方法被调用
模板方法:一般是具体的方法,也就是一个框架,实现对基本方法的调度,完成所需的逻辑功能
//抽象模板类
public abstract class AbstractClass{
//基本方法
protected abstract void doSomething();
//基本方法
protected abstract void doAnything();
//模板方法
public void templateMethod(){
//调用基本方法,完成相关的逻辑功能
this.doSomething();
this.doAnything();
}
}
//具体模板类
public class ConCreteClass1 extends AbstractClass{
//实现基本方法
protected void doSomething(){
}
protected void doAnything(){
}
}
public class ConCreteClass2 extends AbstractClass{
//实现基本方法
protected void doSomething(){
}
protected void doAnything(){
}
}
//场景类
public class Client{
public static void main(String[] args){
AbstractClass class1=new ConCreteClass1();
AbstractClass class2=new ConCreteClass2();
//调用模板方法
class1.templateMethod();
class2.templateMethod();
}
}
优点:①封装可变部分,扩展不变部分,把认为不变的算法封装到父类实现,而可变的则可以通过继承继续扩展;
②提取公共部分的代码,便于维护;
③行为有父类控制,子类实现,基本方法是有子类实现的,因此子类可以通过扩展的方式增加相应的功能
缺点:一般情况下,抽象类负责声明最抽象、最一般的事物的属性和方法,实现类完成具体的事物属性和方法。但模板方法颠倒了,抽象了定义了部分具体的抽象方法,有子类实现,子类执行的结果影响了父类的结果。
应用场景:①多个子类有公共的方法,并且逻辑基本相同;
②重要、复杂的算法,可以核心的算法设计为模板