目录
- 单例模式
- 适配器模式
- Builder模式
- 简单工厂
单例模式
声明:我是全部抄这位大神的文章,作为学习笔记
SingleTon是一种创建模型,指某个类采用了singleton模式,则这个类被创建后,只可能产生一个实例供外部访问,并且提供一个全局的访问点。
核心知识点:
- 单例模式的类的构造方法私有化(采用private修饰)
- 在其内部产生该类的实例化对象,并用private static修饰
- 定义一个静态的方法,返回该类的实例
/**
* 方法一:饿汉式,线程安全,效率低
* 优点:简单,不存在多线程问题,避免了synchronized所造成的性能问题
* 缺点:当SingleTon类被加载的时候,会初始化static的singleTon,静态变量被创建并分配内存空间,
* 从这以后这个static的singleTon对象就一直占用这块内存, 即便你用不到这个实例,
* 当类被卸载的时候,静态的变量被销毁,并释放内存,因此在某些特定的条件下回耗费内存
*/
public class SingleTon{
//static和final修饰
private static final SingleTon singleTon = new SingleTon();
private SingleTon(){ }
public static SingleTon getInstance(){
return singleTon;
}
}
/**
* 方法二:饱汉式,非线程安全
* 优点:简单,当SingleTon类被加载的时候,静态变量singleTon未被创建并分配内存,当getInstance第一次被执行的时候,singleTon的实例才会被
* 创建,并分配内存,所以某些特定条件下节约了内存。
* 缺点:线程并发环境下可能会出现多个SingleTon实例
*/
public class SingleTon{
private static SingleTon singleTon;
private SingleTon(){ }
public static SingleTon getInstance(){
if(singleTon==null){
singleTon = new SingleTon();
}
return singleTon;
}
}
/**
* 方法三:饱汉式,线程安全简单实现
* 优点:使用synchronized关键字避免多线程访问时,出现多个SingleTon实例
* 缺点:同步方法频繁调用时,效率略低
*/
public class SingleTon{
private static SingleTon singleTon;
private SingleTon(){}
public static synchronized SingleTon getInstance(){
if(singleTon==null){
singleTon = new SingleTon();
}
return singleTon;
}
}
/**
* 方法四:单例模式最优方案,线程安全且效率高
*
*/
public class SingleTon{
private static volatile SingleTon singleTon; //volatile修饰,保证了多线程访问的一个变量值统一
private SingleTon(){}
public static SingleTon getInstance(){
if(singleTon==null){
synchronized(SingleTon.class){
if(singleTon==null){
singleTon=new SingleTon();
}
}
}
return singleTon;
}
}
/**
* 方法五:简单高效,多线程可用,按需创建,节省空间
* SingleTon创建内部类SingleLoader不会创建
* 只有外部调动SingleTon.getInstance时,才会加载内部类
*/
public class SingleTon {
private SingleTon(){}
private static class SingleLoader{
private static final SingleTon instance = new SingleTon();
}
public static SingleTon getInstance(){
return SingleLoader.instance;
}
}
适配器模式
参考资料:
http://www.cnblogs.com/imeiling/p/6394738.html
http://blog.csdn.net/u011240877/article/details/52601040
什么是适配器模式,简单的说就是开发中我们设计了一个接口,但是由于某种原因这个接口不满足我们的需求,比如处理的逻辑不同等导致我们不能复用这个接口,这时就需要自己创造一个适配器,来满足需求,提高代码的兼容性。这个适配器可以是一个类也可以是一个对象。
应用场景
A类需要调用M方法,B类中有M方法,但是如果A直接调用B的M方法,得到的结果并不满足A的需求。这样的设计B类被写死,不符合我们编程复用性的思想。所以我们可以把B类设计成一个接口,再实现出一些其他类,供其他有特殊需求的类使用,比如A类。
两种类型
- 类适配器
- 对象适配器
类适配器:
- 设计一个接口K,让他有M方法
- 在B类中创建一个specialM方法,处理A类的特殊需求
- 让A类继承B类,并实现K接口,A中拥有了M方法
- 在A类的M方法中,用super.specialM()方式调用B类的M方法
对象适配器:
- 设计一个接口K,让他有M方法
- 在B类中创建一个specialM方法,处理A类的特殊需求
- A类实现K接口,并在A类中声明一个B类成员变量,通过构造方法传入。
- 如果需要,在A的M方法中,调用b变量的specialM方法
总之,两端不变,通过我们创建的适配器来,满足需求,这就是适配器。
代码
场景:一位中国人不会英语,他需要通过翻译来和外国人交流
// 说汉语的接口
public interface SayChinese {
void sayChinese(String s);
}
// 能说英语的类适配器
public class SayEnglish {
public void sayEnglish(String s){
// 说的英文
Log.e("TAG","my god, I can speak english"+s);
}
}
类适配器写法:
// 翻译类
public class Translator extends SayEnglish implements SayChinese {
// 翻译类拥有了说汉语的方法
@Override
public void sayChinese(String s) {
// 调用说英文的方法
super.sayEnglish(s);
}
}
Translator translator = new Translator();
translator.sayChinese("我是中国人");
对象适配器写法:
public class Translator implements SayChinese {
public SayEnglish english;
public Translator(SayEnglish sayEnglish){
this.english = sayEnglish;
}
// 翻译类用有了说中文的方法
@Override
public void sayChinese(String s) {
// 调用说英文的方法
//super.sayEnglish(s);
english.sayEnglish(s);
}
}
SayEnglish english = new SayEnglish();
Translator translator = new Translator(english);
translator.sayChinese("我是中国人");
Builder模式
学习资料(非常敬佩这位作者,原来知识可以这样讲)
http://blog.lmj.wiki/2016/11/13/design-pattern/builder/
什么是Builder模式,先从字面意思可以知道是创建者、构造者的意思。那作为创建者,我们就有很大的权利来决定怎样去创造一个对象。比如我们平时创建一个对象,构造方法里面有3个参数,那我们创建对象时,就必须按照顺序传入参数,有一定的限制。那通过builder模式后,我创建复杂的对象时,很自由,有种无拘无束的感觉,以可以少传参数,你再也不用担心顺序的问题。
场景及代码
做为程序员的小光逃离北上广,回家创业卖热干面了,热干面的配料有葱花、香菜、辣椒、酸菜,不同人有不同的需求。期初小光这样做热干面。
public class HotNoodls {
private boolean conghua;
private boolean xiangcai;
private boolean lajiao;
private boolean suancai;
public HotNoodls(boolean conghua, boolean xiangcai, boolean lajiao, boolean suancai) {
this.conghua = conghua;
this.xiangcai = xiangcai;
this.lajiao = lajiao;
this.suancai = suancai;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (conghua) {
builder.append("葱花.");
} else if (xiangcai) {
builder.append("香菜.");
} else if (lajiao) {
builder.append("辣椒.");
} else if (suancai) {
builder.append("酸菜.");
}
return builder.toString();
}
}
来了位客人要一份人干面,只要葱花、香菜,小光做出的热干面:
HotNoodls hotNoodls = new HotNoodls(true,true,false,false);
突然有一天一位客人不要辣椒,方葱花,结果小光做错了,因为这哥们不安套路出牌,导致小光放错配料了。
后来小光想了想,让客户自己放配料,然后我直接拿去做,这样就不会出现错了。于是热干面就成这样的了
public class HotNoodls {
private boolean conghua;
private boolean xiangcai;
private boolean lajiao;
private boolean suancai;
public HotNoodls(Builder builder) {
this.conghua = builder.conghua;
this.xiangcai = builder.xiangcai;
this.lajiao = builder.lajiao;
this.suancai = builder.suancai;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (conghua) {
builder.append("葱花.");
} else if (xiangcai) {
builder.append("香菜.");
} else if (lajiao) {
builder.append("辣椒.");
} else if (suancai) {
builder.append("酸菜.");
}
return builder.toString();
}
public static class Builder{
public boolean conghua;
public boolean xiangcai;
public boolean lajiao;
public boolean suancai;
public Builder withCongHua(){
this.conghua = true;
return this;
}
public Builder withXiangCai(){
this.xiangcai = true;
return this;
}
public Builder withLaJiao(){
this.lajiao = true;
return this;
}
public Builder withSuanCai(){
this.suancai = true;
return this;
}
public HotNoodls build(){
return new HotNoodls(this);
}
}
}
一份热呼呼的热干面上来啦,这下就不会出现给客人放错配料的问题了
HotNoodls hotNoodls = new HotNoodls.Builder()
.withCongHua()
.withLaJiao()
.build();
简单工厂模式
继小光卖热干面后,他又卖饮料来作为一种配套营销模式,开始小光这样做饮料,如橙汁:
public class OrangeJuice {
public void make(){
// 1. 拿出一次性饮料杯
System.out.println("拿出一次性饮料杯");
// 2. 加入速溶橙汁粉
System.out.println("加入速溶橙汁粉");
// 3. 加水冲兑
System.out.println("加水");
// 4. 加盖, 打包
System.out.println("加盖, 打包");
}
}
因为加入不同的速溶粉,才能制作出不同的果汁,所以这样的方式肯定不合理,于是效果这样做果汁,提高了扩展性。
public abstract class Drink {
public void make(){
// 1. 拿出一次性饮料杯
System.out.println("拿出一次性饮料杯");
// 2. 加入速溶橙汁粉
System.out.println("加入"+getInstanceName());
// 3. 加水冲兑
System.out.println("加水");
// 4. 加盖, 打包
System.out.println("加盖, 打包");
}
abstract String getInstanceName();
}
public class OrangeJuice extends Drink {
@Override
String getInstanceName() {
return "橙汁";
}
}
public class AppleJuice extends Drink {
@Override
String getInstanceName() {
return "苹果汁";
}
}
这样的话,小光每次制作不同的饮料的时候都需要这样
OrangeJuice orangeJuice = new OrangeJuice();
orangeJuice.make();
而我们的工厂模式是想通过向工厂中传入一些参数就会创建出对应的实力。所以我们还需要改造,如下:
public class DrinkFactory {
public static Drink creat(String drinkName){
switch (drinkName){
case "橙汁":
return new OrangeJuice();
case "苹果":
return new AppleJuice();
default:
return new OrangeJuice();
}
}
}
这样就是我的工厂模式的freestyle了
Drink drink = DrinkFactory.creat("橙汁");
drink.make();