一、Singleton单例模式
单例指的只能存在唯一的一个实例对象(单例)
单例模式的设计思路:先阻止类可以类外部通过new的方式(构造函数)创建实例,并在类的内部创建一个获得该类实例的静态方法,用来创建该类实例(不存在实例时)或者返回实例(存在实例时)从而实现单一实例的控制。
实现例程如下,经典的饿汉式例程和懒汉式例程:
饿汉式例程:
public class HungryMan{
private HungerMan(){};
privatestatic final HungerMan hungerman = new HungerMan();
publicstatic HungerMan getInstance(){
return hungerman;
}
}
懒汉式例程:
Public class LazyMan{
private LazyMan(){}
private static LazyMan lazyman = null;
public static LazyMan getlazyman(){
if(lazyman== null){
synchronized(LazyMan.class){
if(lazyman== null){lazyman = new LazyMan();}
}
}
}
return lazyman;
}
(所谓的饿汉式和懒汉式的定义,并不是站在上帝视角去定义的,而是从程序视角定义的,在定义hungerman时,饿汉式就一股劲的迫不及待的去定义完整(因为很饿),懒汉式就先声明个对象引用就不继续了(因为很懒,老想着以后的事情以后再做好了),所以把定义工作放在要用到的时候再去定义,所以放在getlazyman上。)
可以看到,Singleton模式首先先对其构造方法的权限声明为private,阻止类外部通过构造方法创建实例,再提供get方法来获取唯一实例。但是要特别注意的是,在懒汉式例程中get方法内部采用了synchronized锁声明(只允许一个线程进入)。如果没有声明的情况下,如下:
public static LazyMan getlazyman(){
if(lazyman== null){ lazyman = new LazyMan(); }
return lazyman;
}
在多线程下使用是非常危险的(不安全的),有可能出现这种情况,唯一实例并未创建时,多个线程都调用类内部创建类的方法,而且都运行到if(lazyman == null)内部而且在运行lazyman = newLazyMan();之前的地方,这就非常尴尬了,这个时候lazyman=null,if里的条件语句是true,所以可以进入到if内部,也就多个线程都通过了我们原本为了限制实例数量的判断语句,而且下一步都是lazyman= new LazyMan();,这样在堆中就存在多个LazyMan实例了,这就和我们预期遐想的不同了。
二、Template模式(模板模式)
模板模式,顾名思义,设定了模板,并让接下来代码实现都按照一个模板进行,说到模板,很容易就联想到了抽象类和接口的运用,定义了方法名,没有方法体,然后让子类去实现、继承、扩展他们的方法,那么,抽象类和接口的方法不妨就充当了“模板”的作用,也就是骨架,这就是模板模式。
在模板模式中,可分为抽象模板(AbstractTemplate)和具体模板(Concrete Template)
抽象模板也就是骨架,定义一个或多个操作(方法),以便被子类实现。
具体模板指的就是对抽象模板的实现,也可以说就是子类。
在抽象模板中的基础方法又可以分为:抽象方法(AbstractMethod)、具体方法(Concrete Method)、钩子方法(Hook Method)
抽象方法对应抽象类中的抽象方法,具体方法对应抽象类中具体方法,钩子方法对应抽象类(接口)中的空方法。
例程:
//定义了一个抽象类,名字为SteamRice(煮饭、蒸饭),方法分别为PutRice(下米)、WashRice(洗米)、CookRice(煮米)
//这个类说明了煮饭的基本过程,是煮饭的骨架,什么饭都是这个步骤。
//而它的子类就对其进行了不同的实现,但是骨架还是不变的。
public abstract class SteamRice{
public abstract void PutRice();
public abstract void WashRice();
public abstract void CookRice();
}
public class ZhenZhuMi extends SteamRice{
public void PutRice(){System.out.println("下珍珠米");}
public void WashRice(){System.out.println("洗一次");}
public void CookRice(){System.out.println("水位高于米3cm,用砂锅煮");}
}
public class JianMi extends SteamRice{
public void PutRice(){System.out.println("下尖米");}
public void WashRice(){System.out.println("洗两次");}
public void CookRice(){System.out.println("水位高于米1.5cm,用电饭锅煮");}
}
三、Strategy策略模式
在模板设计模式中,我们是通过抽象类(或者实现接口)制作模板,通过继承抽象类(或者实现接口)来实现模板,是一种重心放在子类上的逻辑。而策略模式其逻辑是反过来的,是一种重心放在父类上的逻辑,主要是通过父类对象对子类改写的方法进行调用。
在策略模式中,可以通过策略(Strategy)一词来理解这个模式的逻辑,在逻辑上将策略的作用(目的)和策略的具体实施计划分开,父类被称为抽象策略(Strategy),也就是相当策略的作用(目的),只提供一个骨架,而其子类被称为具体策略(ConcreteStrategy),也就是相当策略的具体实施计划,每个子类都是一个计划。当然,既然是策略,那么就有策略的使用者,这个使用者在策略模式中称为Context(上下文、环境),正如上面所说的,在Context中创建一个Strategy的对象引用去调用ConcreteStrategy的具体实现。
所以,策略模式是相当于对一系列解决方案(或算法等)包装到一系列的策略类里面去,然后通过父类对象去访问具体实现策略的子类,而提供多种解决方案,因为这些方案都是解决相同的问题,所以这些方案都可以互换,都不会影响使用方案的客户端。
采用了模板模式的例子进行补充:
例程一:通过传入米的类型
public class Context {
private SteamRice steamRice;
private String RiceType;
public Context(String RiceType){
this. RiceType = RiceType;
}
public void contextInterface(){
if(RiceType. equals(珍珠米)){
steamRice= new ZhenZhuMi();
}else if(RiceType. equals(尖米)){
steamRice = new JianMi();
}
steamRice.PutRice();
steamRice.WashRice();
steamRice.CookRice();
}
}
例程二:直接传入子类对象向上转型
public class Context {
private SteamRice steamRice;
public Context(SteamRice steamRice){
this. steamRice = steamRice;
}
public void contextInterface(){
steamRice.PutRice();
steamRice.WashRice();
steamRice.CookRice();
}
}
------------------------------------------------分割线----------------------------------------------------------
上文如有错误、写得不合理以及有疑惑的地方,希望您可以在评论区提出。
在下十分感谢。
如果只是想在评论区吐吐槽、聊聊心得、卖个萌,同样也十分欢迎。
祝大家生活美好,干杯!~( ゜▽゜)つロ
转载请注明原作者以及附上原文章地址,谢谢。