Java设计模式一
2016-12-27 22:07
246 查看
本文内容来自慕课网系列课程,记录下学习的内容。
饿汉模式
饿汉模式:类加载的时候就会创建唯一的一个类实例
懒汉模式
懒汉模式:类加载的时候并没有去创建类的实例
区别:
饿汉模式加载类时比较慢,但在运行时获取对象的速度比较快,线程安全
懒汉模式加载类时比较快,但在运行时获取对象的速度比较慢,线程不安全
参考Thread-Safe and a Fast Singleton Implementation – Singleton Design Pattern in java,线程安全的单例模式,可以这样写:
基本方法
抽象方法
可选的钩子
Template方法(final)
具体子类
实现基类中的抽象方法
覆盖钩子方法
准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性,最后将方法汇总构成一个不可改变的模板方法。
使用场景:
1.算法或操作遵循相似的逻辑
2.重构时(把相同的代码提取到父类中)
3.重要、复杂的算法,核心算法设计为模板方法
优点:封装性好、复用性好、屏蔽细节、便于维护
这里使用的是一个炮制饮料的例子,分为炮制咖啡和茶,总共4步,其中有两步不同。
其抽象基类为
创建
钩子使子类更灵活
现在假设另一中情况,假设有些顾客并不想添加配料,即不想执行
Hook,钩子函数,提供一个默认或空的实现。具体的子类可以自行决定是否挂钩以及如何挂钩。
修改
在子类中就可以覆写
适配器模式将一个类的接口,转换成客户期望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
这个例子是插座适配器,一个笔记本只能使用三相插座,但是现在只有一个二相插座
使用组合的方式实现称为对象适配器
特点:把”被适配者”作为一个对象组合到适配器类中,以修改目标接口包装被适配者
三相插座接口
二相插座类
笔记本类
使用继承方式称为类适配器
特点:通过多重继承不兼容接口,实现对目标接口的匹配,单一的为某个类而实现适配
Java设计模式一
单例模式
有些对象我们只需要一个,比如:配置文件、工具类、线程池、缓存、日志对象等。如果创造出多个实例,就会导致许多问题,比如占用过多资源,不一致的结果等。饿汉模式
饿汉模式:类加载的时候就会创建唯一的一个类实例
public class Singleton { //1.将构造方法私有化,不允许外部直接创建对象 private Singleton() { } //2.创建类的唯一实例 private static Singleton instance = new Singleton(); //3.提供一个用于获取实例的方法 public static Singleton getInstance() { return instance; } }
懒汉模式
懒汉模式:类加载的时候并没有去创建类的实例
public class Singleton2 { //1.将构造方法私有化,不允许外边直接创建对象 private Singleton2() { } //2.声明类的唯一实例,使用private static修饰 private static Singleton2 instance; //3.提供一个用户获取实例的方法 public static Singleton2 getInstance() { if (instance == null) { instance = new Singleton2(); } return instance; } }
区别:
饿汉模式加载类时比较慢,但在运行时获取对象的速度比较快,线程安全
懒汉模式加载类时比较快,但在运行时获取对象的速度比较慢,线程不安全
参考Thread-Safe and a Fast Singleton Implementation – Singleton Design Pattern in java,线程安全的单例模式,可以这样写:
package com.crunchify.tutorials; public class CrunchifySingleton { private static CrunchifySingleton instance = null; protected CrunchifySingleton() { } // Lazy Initialization (If required then only) public static CrunchifySingleton getInstance() { if (instance == null) { // Thread Safe. Might be costly operation in some case synchronized (CrunchifySingleton.class) { if (instance == null) { instance = new CrunchifySingleton(); } } } return instance; } }
模板方法模式
抽象基类定义框架,为所有子类提供一个算法框架基本方法
抽象方法
可选的钩子
Template方法(final)
具体子类
实现基类中的抽象方法
覆盖钩子方法
准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性,最后将方法汇总构成一个不可改变的模板方法。
使用场景:
1.算法或操作遵循相似的逻辑
2.重构时(把相同的代码提取到父类中)
3.重要、复杂的算法,核心算法设计为模板方法
优点:封装性好、复用性好、屏蔽细节、便于维护
这里使用的是一个炮制饮料的例子,分为炮制咖啡和茶,总共4步,其中有两步不同。
其抽象基类为
RefreshBeverage,其中的
addCondiments和
brew方法要留给子类去实现:
/** * 抽象基类,为所有子类提供一个算法框架 * * 提神饮料 */ public abstract class RefreshBeverage { public final void prepareBeverageTemplate() { //步骤1 将水煮沸 boilWater(); //步骤2 炮制饮料 brew(); //步骤3 将饮料倒入杯中 pourInCup(); //步骤4 加入调味料 addCondiments(); } //抽象的基本方法 protected abstract void addCondiments(); private void pourInCup() { System.out.println("将饮料倒入杯中..."); } //抽象的基本方法 protected abstract void brew(); private void boilWater() { System.out.println("将水煮沸..."); } }
创建
Coffee子类,实现抽象类的方法:
/* * 具体子类,提供了coffee的制备方法 */ public class Coffee extends RefreshBeverage { @Override protected void addCondiments() { System.out.println("加入糖和牛奶..."); } @Override protected void brew() { System.out.println("用沸水冲泡咖啡..."); } }
钩子使子类更灵活
现在假设另一中情况,假设有些顾客并不想添加配料,即不想执行
addCondiments()方法,怎样做会更灵活?
Hook,钩子函数,提供一个默认或空的实现。具体的子类可以自行决定是否挂钩以及如何挂钩。
修改
prepareBeverageTemplate()方法如下:
public final void prepareBeverageTemplate() { //步骤1 将水煮沸 boilWater(); //步骤2 炮制饮料 brew(); //步骤3 将饮料倒入杯中 pourInCup(); if(isCustomerWantsCondiments()){ //步骤4 加入调味料 addCondiments(); } } /* * Hook,钩子函数,提供一个默认或空的实现 * 询问用户是否加入调料 */ protected boolean isCustomerWantsCondiments() { return true; }
在子类中就可以覆写
isCustomerWantsCondiments()方法
适配器模式
所谓适配器,就是连接“源”和“目标”的纽带适配器模式将一个类的接口,转换成客户期望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
这个例子是插座适配器,一个笔记本只能使用三相插座,但是现在只有一个二相插座
使用组合的方式实现称为对象适配器
特点:把”被适配者”作为一个对象组合到适配器类中,以修改目标接口包装被适配者
三相插座接口
ThreePlugInterface
/* * 目标方法接口 * * 三相插座接口 */ public interface ThreePlugInterface { //使用三相电流供电 public void powerWithThree(); }
二相插座类
GBTwoPlug
public class GBTwoPlug { //使用二相电流供电 public void powerWithTwo() { System.out.println("使用二相电流供电"); } }
TwoPlugAdapter适配器类实现
ThreePlugInterface接口,持有一个
GBTwoPlug
/** * 二相转三相的插座适配器 * @author Miller * */ public class TwoPlugAdapter implements ThreePlugInterface { private GBTwoPlug plug; public TwoPlugAdapter(GBTwoPlug plug) { this.plug = plug; } @Override public void powerWithThree() { plug.powerWithTwo(); } }
笔记本类
NoteBook
public class NoteBook { private ThreePlugInterface plug; public NoteBook(ThreePlugInterface plug) { this.plug = plug; } //使用插座充电 public void charge() { plug.powerWithThree(); } public static void main(String[] args) { GBTwoPlug twoPlug = new GBTwoPlug(); ThreePlugInterface threePlug = new TwoPlugAdapter(twoPlug); NoteBook noteBook = new NoteBook(threePlug); noteBook.charge(); } }
使用继承方式称为类适配器
特点:通过多重继承不兼容接口,实现对目标接口的匹配,单一的为某个类而实现适配
TwoPlugAdapterExtends类继承自
GBTwoPlug类,实现了
ThreePlugInterface接口
public class TwoPlugAdapterExtends extends GBTwoPlug implements ThreePlugInterface { @Override public void powerWithThree() { this.powerWithTwo(); } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Debian 7.x 安装Oracle JAVA
- springmvc实现url路由功能
- spring boot 配置 druid/** * 配置druid * Created by adam on 4/11/16. */ @Configuration public class D
- api接口rsa加密