1.单例模式:保证类的对象在内存中有且仅有一份。Spring中管理的对象都有对应的生命周期,对于scope配置为singleton的bean都是单例的,这也是Spring管理的对象的默认的生命周期。
实现1--饿汉式
public class Singleton { private static final Singleton single = new Singleton();
private Singleton() { }
public static final Singleton getInstance() { return single; } }
实现2--懒汉式
- 错误示例:这种方式的实现虽然延迟加载减小了内存占用,但在多线程时无法保证线程安全性,假设第一个线程执行到步骤(2)时,但是尚未完成对象的初始化过程,第二个线程执行到步骤(1)则if返回的结果为true,会导致内存中存在不唯一的single对象。
public class Singleton { private static Singleton single = null;
private Singleton(){ }
public static Singleton getInstance(){ if(single == null){ // (1) single = new Singleton(); //(2) } return single; } }
- 改进方式1:使getInstance()方法成为同步方法或者使用同步代码块。但是这样方法的效率就会很低下。
public class Singleton { private static Singleton single = null; private Singleton(){ } public static Singleton getInstance() { synchronized (Singleton.class) { if (single == null) { single = new Singleton(); } return single; } } }
- 改进方式2:DCL-双重检测锁。双重检测锁在方式1的基础上提高了效率,只在第一次创建的时候会加锁,但是需要注意的是如果single对象没有使用 volatile关键字修饰依然是错误的,详细分析见博客:http://cmsblogs.com/?p=2161&from=timeline&isappinstalled=0
public class Singleton { private volatile static Singleton single = null; private Singleton() { } public static Singleton getInstance() { if (single == null) { synchronized (Singleton.class) { if (single == null) { single = new Singleton(); } } } return single; } }
2 . 模板模式:一般用于多个子类有共同的方法,父类里面定义好了方法的调用逻辑。例如Junit里面的@Test方法就使用了模板方法
/**
* 定义一个是抽象类作为模板方法类,子类继承这个类 ,overide需要使用的方法(如果定义成接口,则实现类需要实现所有方法)
* 例如这里templateMethod方法按顺序执行三个方法,实现类也会按顺序执行这个方法
* @author niepei
*/
public abstract class Template { public abstract void start(); public abstract void process(); public abstract void end(); public void test(){ this.start(); this.process(); this.end(); } } public class SubTemplate extends Template { public void start() { System.out.println("第一步:start"); } public void end() { System.out.println("第三步:end"); } public void process() { System.out.println("第二步:process"); } public static void main(String[] args) { Template template = new SubTemplate(); template.test(); } } // 打印结果如下: 第一步:start 第二步:process 第三步:end
3. 策略模式:策略模式定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的变化不会影响到使用算法的客户,JDK 中的Comparator比较器就采用了策略模式。
// 抽象策略类接口 public interface Strategy { // 返回两个操作数的结果 public int getResult(int a,int b); } // 加法策略类 public class StrategyAdd implements Strategy { @Override public int getResult(int a,int b) { return a+b; } } // 乘法策略类 public class StrategyMultiple implements Strategy { @Override public int getResult(int a,int b) { return a*b; } } // 策略类的包装类 public class Context { private Strategy stragety; public Context(Strategy stragety) { this.stragety = stragety; } public int getResult(int a,int b) { return stragety.getResult(a,b); } public static void main(String[] args) { int a = 2,b=5; Context context; context = new Context(new StrategyAdd()); System.out.println(context.getResult(a, b)); context = new Context(new StrategyMultiple()); System.out.println(context.getResult(a,b)); } }
4.装饰模式:给一个对象动态增加一些新的功能,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例。JDK中的IO流以及mybatis中的query就使用了装饰者设计模式。
public interface IPicture { public void showPicture(); } // 被装饰者 public class Picture implements IPicture{ @Override public void showPicture() { System.out.println("this is a pretty picture"); } } // 装饰者 public class PictureDecorator implements IPicture{ private IPicture picture; public PictureDecorator(IPicture picture){ this.picture = picture; } @Override public void showPicture() { System.out.println("the author of this picture is Van Gogh,"); this.picture.showPicture(); System.out.println("It's name is sunflower"); } public static void main(String args[]){ IPicture picture = new Picture(); IPicture pictureDecorator = new PictureDecorator(picture); pictureDecorator.showPicture(); } }
// 打印结果如下
the author of this picture is Van Gogh,
this is a pretty picture
It's name is sunflower
5.适配器模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
public class Source { public void method2() { System.out.println("this is method2"); } } public interface Target { public void method1(); } // 组合方式实现适配器 public class Adapter implements Target { private Source source; public Adapter(Source source){ this.source = source; } @Override public void method1() { source.method2(); } public static void main(String[] args){ Target target = new Adapter(new Source()); target.method1(); } }
7.代理模式:使用一个代理类来代替原先类进行操作。代理分为静态代理(对目标对象进行封装,调用目标对象的方法即可)和动态代理(运行时生成代理对象)。Spring的AOP技术就是基于动态代理实现的。
public interface IGamePlayer { public void killMonster(); } // 目标类--游戏玩家 public class GamePlayer implements IGamePlayer{ private String name; @Override public void killMonster() { System.out.println(this.name + " is killing monster"); } }
// 代理类--游戏代练 public class GamePlayerProxy implements IGamePlayer { private IGamePlayer player; public GamePlayerProxy(IGamePlayer player) { this.player = player; } @Override public void killMonster() { this.player.killMonster(); } //代理类除了完成被代理类的方法,还可以拥有自己的方法 public void getPay() { System.out.println("一共收取费用 150¥"); }
public static void main(String[] args) { IGamePlayer player = new GamePlayer("pepper"); IGamePlayer proxyPlayer = new GamePlayerProxy(player); proxyPlayer.killMonster(); proxyPlayer.upgrade(); } }
8.享元模式:主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。
/** * 适用于作共享的一些个对象,他们有一些共有的属性,就拿数据库连接池来说,url、driverClassName、 * username、password及dbname,这些属性对于每个连接来说都是一样的,所以就适合用享元模式来处理, * 建一个工厂类,将上述类似属性作为内部数据,其它的作为外部数据,在方法调用时,当做参数传进来,这样就节省了空间,减少了实例的数量。 * * 下面的例子是是数据库连接池的代码 * 通过连接池的管理,实现了数据库连接的共享,不需要每一次都重新创建连接,节省了数据库重新创建的开销,提升了系统的性能 * @author pepper * */ public class ConnectionPool { private List<Connection> pool; /*公有属性*/ private String url = "jdbc:mysql://localhost:3306/test"; private String username = "root"; private String password = "root"; private String driverClassName = "com.mysql.jdbc.Driver"; private int poolSize = 100; @SuppressWarnings("unused") private static ConnectionPool instance = null; Connection conn = null; /*构造方法,做一些初始化工作*/ private ConnectionPool() { pool = new ArrayList<Connection>(poolSize); for (int i = 0; i < poolSize; i++) { try { Class.forName(driverClassName); conn = DriverManager.getConnection(url, username, password); pool.add(conn); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } } /* 返回连接到连接池 */ public synchronized void release() { pool.add(conn); } /* 返回连接池中的一个数据库连接 */ public synchronized Connection getConnection() { if (pool.size() > 0) { Connection conn = pool.get(0); pool.remove(conn); return conn; } else { return null; } } }
9.工厂方法模式:使用工厂去管理对象的创建,而不是创建者自身。最典型的工厂模式使用者就是Spring,Spring内部的IOC容器就是一个工厂,所有bean的创建、销毁、注入都由这个容器管理。工厂模式分工厂方法模式和抽象工厂模式。它们的区别在于抽象工厂抽象程度更高,把工厂也抽象成了一个接口,这样可以再每添加一个新的对象的时候而不需要修改工厂的代码。
- 工厂方法模式:
// 抽象产品接口
public interface Human { public void showSkinColor(); } // 具体的产品类1 public class Human_Black implements Human { @Override public void showSkinColor() { System.out.println("my color is balck"); } } // 具体的产品类2 public class Human_White implements Human { @Override public void showSkinColor() { System.out.println("my color is white"); } } // 抽象工厂接口 public abstract class AbstractHumanFactory { public abstract <T extends Human> T createHuman(Class<T> c); } // 具体的工厂类 public class HumanFactory extends AbstractHumanFactory { @Override public <T extends Human> T createHuman(Class<T> c) { Human human = null; try { human = (Human) Class.forName(c.getName()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return (T) human; } }
- 抽象工厂模式 :工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,为了解决这个问题就用到了抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
// 抽象产品类A--电车 public abstract class ElectroCar { public abstract void showCarInfo(); public void engineBy() { System.out.println("this car is engineBy electricity!"); } } // 抽象产品类A的具体产品类1--BYD public class ElectroCar_BYD extends ElectroCar{ @Override public void showCarInfo() { System.out.println("this is BYD Car,it belongs ElectroCar"); } } // 抽象产品类A的具体产品类2--Tesla public class ElectroCar_Tesla extends ElectroCar{ @Override public void showCarInfo() { System.out.println("this is Tesla Car,it belongs ElectroCar"); } } // 抽象产品类B public abstract class GasCar { public abstract void showCarInfo(); public void engineBy() { System.out.println("this car is engineBy Gasoline!"); } } // 抽象产品类B的具体产品类1--Benz public class GasCar_Benz extends GasCar{ @Override public void showCarInfo() { System.out.println("this is Benz Car,it belongs GasCar"); } } // 抽象产品类B的具体产品类2--BMW public class GasCar_BMW extends GasCar { @Override public void showCarInfo() { System.out.println("this is BMW Car,it belongs GasCar"); } } // 抽象工厂类 public abstract class AbstractCarFactory { public abstract GasCar createGasCar(); public abstract ElectroCar createElectroCar(); } // 具体工厂类1--生产B1和A2 public class CarFactory1 extends AbstractCarFactory { @Override public GasCar createGasCar() { return new GasCar_Benz(); } @Override public ElectroCar createElectroCar() { return new ElectroCar_Tesla(); } } // 具体工厂类2--生产B2和A1 public class CarFactory2 extends AbstractCarFactory{ @Override public GasCar createGasCar() { return new GasCar_BMW(); } @Override public ElectroCar createElectroCar() { return new ElectroCar_BYD(); } } public class Client { public static void main(String[] args) { AbstractCarFactory carFactory1 = new CarFactory1(); carFactory1.createGasCar().showCarInfo(); carFactory1.createElectroCar().showCarInfo(); AbstractCarFactory carFactory2 = new CarFactory2(); carFactory2.createGasCar().showCarInfo(); carFactory2.createElectroCar().showCarInfo(); } }
参考博客:http://www.importnew.com/24128.html