Java常用设计模式总结
单例,又分5种:
1、初级懒汉模式,只适合单线程环境(不好)
2、懒汉式,多线程的情况可以用(性能不好,每个线程执行到时都会被资源的锁给限制)
3、懒汉式,双重校验锁(还可以)
4、饿汉模式(天生线程安全,建议使用)
缺点:没有lazy loading的效果,从而降低内存的使用率
5、静态内部内。(建议使用)
优点:达到了lazy loading的效果,即按需创建实例
例子:
//最初级的懒汉模式,只适合单线程环境(不好) class Singleton { // 1.将构造方法私有化,不允许外边直接创建对象 private Singleton(){ } // 2.声明(不是创建)类的唯一实例,使用private static private static Singleton instance; // 3.提供一个用于获取实例的方法,使用public static public static Singleton getInstance(){ // 第一线程来的时候提示没有实例程序就创建一个实例,第二个人来的时候一判断程序有实力对象了就不在创建实例对象,保证实例唯一性 if(instance==null){ instance=new Singleton(); } return instance; } public void showMessage() { System.out.println("Hello World!"); } } //懒汉式,多线程的情况可以用(性能不好,每个线程执行到时都会被资源的锁给限制) class Singleton2 { private static Singleton2 instance=null; private Singleton2(){ } public static synchronized Singleton2 getInstance(){ if(instance==null){ instance=new Singleton2(); } return instance; } public void showMessage() { System.out.println("Hello World!"); } } //懒汉式,双重校验锁(还可以) class Singleton3 { private static Singleton3 instance=null; private Singleton3(){ } public static Singleton3 getInstance(){ if(instance==null){ synchronized(Singleton3.class){ if(instance==null){ instance=new Singleton3(); } } } return instance; } public void showMessage() { System.out.println("Hello World!"); } } //下面是饿汉模式(天生线程安全,建议使用) //缺点:没有lazy loading的效果,从而降低内存的使用率。 class Singleton4 { // 创建单例模式第一步:将构造方法私有化private,不允许外部直接创建对象 private Singleton4() { } // 在类中创建类的唯一实例,加static,为了安全起见最好将实例对象私有化private private static Singleton4 instance = new Singleton4(); // 提供一个用于获取实例的方法,必须static public static Singleton4 getInstance() { return instance; } public void showMessage() { System.out.println("Hello World!"); } } //静态内部内。(建议使用) //优点:达到了lazy loading的效果,即按需创建实例。 class Singleton5 { private Singleton5(){ } private static class SingletonHolder{ private final static Singleton5 instance=new Singleton5(); } public static Singleton5 getInstance(){ return SingletonHolder.instance; } public void showMessage() { System.out.println("Hello World!"); } } /** * 单例模式Singleton 应用场合:有些对象只需要一个就足够了,如皇帝,老婆 * 作用:保证整个应用程序中某个实例有且只有一个 * 主要分两种类型,懒汉模式和饿汉模式,但又细分成五种 * @author cdzhujun * */ public class SingletonPatternDemo { public static void main(String[] args) { // 不合法的构造函数 // 编译时错误:构造函数 Singleton() 是不可见的 // Singleton object = new Singleton(); System.out.println("—————懒汉模式1—————"); Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); if (s1 == s2) { System.out.println("s1和s2是同一个实例"); } else { System.out.println("s1和s2不是同一个实例"); } // 显示消息 s1.showMessage(); System.out.println("—————懒汉模式2—————"); Singleton2 s3 = Singleton2.getInstance(); Singleton2 s4 = Singleton2.getInstance(); if (s3 == s4) { System.out.println("s3和s4是同一个实例"); } else { System.out.println("s3和s4不是同一个实例"); } // 显示消息 s3.showMessage(); System.out.println("—————懒汉模式3—————"); Singleton3 s5 = Singleton3.getInstance(); Singleton3 s6 = Singleton3.getInstance(); if (s5 == s6) { System.out.println("s5和s6是同一个实例"); } else { System.out.println("s5和s6不是同一个实例"); } // 显示消息 s5.showMessage(); System.out.println("—————饿汉模式—————"); Singleton4 s7 = Singleton4.getInstance(); Singleton4 s8 = Singleton4.getInstance(); if (s7 == s8) { System.out.println("s7和s8是同一个实例"); } else { System.out.println("s7和s8不是同一个实例"); } s7.showMessage(); System.out.println("—————懒汉模式5—————"); Singleton5 s9 = Singleton5.getInstance(); Singleton5 s0 = Singleton5.getInstance(); if (s9 == s0) { System.out.println("s9和s0是同一个实例"); } else { System.out.println("s9和s0不是同一个实例"); } // 显示消息 s9.showMessage(); } }
执行结果:
—————懒汉模式1————— s1和s2是同一个实例 Hello World! —————懒汉模式2————— s3和s4是同一个实例 Hello World! —————懒汉模式3————— s5和s6是同一个实例 Hello World! —————饿汉模式————— s7和s8是同一个实例 Hello World! —————懒汉模式5————— s9和s0是同一个实例 Hello World!
工厂模式,又分3种:
1、简单工厂模式:将创建(new)的工作交给一个工厂类来做。
abstract class BMW1 { public BMW1() { } } class BMW320 extends BMW1 { public BMW320() { System.out.println("制造-->BMW320"); } } class BMW523 extends BMW1 { public BMW523() { System.out.println("制造-->BMW523"); } } class Factory { public BMW1 createBMW(int type) { switch (type) { case 320: return new BMW320(); case 523: return new BMW523(); default: break; } return null; } } /** * 工厂模式演示:简单工厂模式 * @author cdzhujun * */ public class FactoryPatternDemo { public static void main(String[] args) { Factory factory = new Factory(); BMW1 bmw320 = factory.createBMW(320); BMW1 bmw523 = factory.createBMW(523); } }
执行结果:
制造-->BMW320 制造-->BMW523
2、工厂方法模式:不再由一个工厂类具体实例化,而是抽象出来,子工厂负责创建(new)。
abstract class BMW2 { public BMW2(){ } } class BMW320_2 extends BMW2 { public BMW320_2() { System.out.println("制造-->BMW320"); } } class BMW523_2 extends BMW2{ public BMW523_2(){ System.out.println("制造-->BMW523"); } } interface FactoryBMW { BMW2 createBMW(); } class FactoryBMW320 implements FactoryBMW{ @Override public BMW320_2 createBMW() { return new BMW320_2(); } } class FactoryBMW523 implements FactoryBMW { @Override public BMW523_2 createBMW() { return new BMW523_2(); } } /** * 工厂方法模式 * @author cdzhujun * */ public class FactoryPatternDemo2 { public static void main(String[] args) throws Exception { FactoryBMW320 factoryBMW320 = new FactoryBMW320(); BMW320_2 bmw320 = factoryBMW320.createBMW(); FactoryBMW523 factoryBMW523 = new FactoryBMW523(); BMW523_2 bmw523 = factoryBMW523.createBMW(); } }
执行结果:
制造-->BMW320 制造-->BMW523
3、抽象工厂模式:将产品也进行抽象,各个子工厂类根据需求具体创建(new)。
//发动机以及型号 interface Engine { } class EngineA implements Engine{ public EngineA(){ System.out.println("制造-->EngineA"); } } class EngineB implements Engine{ public EngineB(){ System.out.println("制造-->EngineB"); } } //空调以及型号 interface Aircondition { } class AirconditionA implements Aircondition{ public AirconditionA(){ System.out.println("制造-->AirconditionA"); } } class AirconditionB implements Aircondition{ public AirconditionB(){ System.out.println("制造-->AirconditionB"); } } //创建工厂的接口 interface AbstractFactory { //制造发动机 public Engine createEngine(); //制造空调 public Aircondition createAircondition(); } //为宝马320系列生产配件 class FactoryBMW320_2 implements AbstractFactory{ @Override public Engine createEngine() { return new EngineA(); } @Override public Aircondition createAircondition() { return new AirconditionA(); } } //宝马523系列 class FactoryBMW523_2 implements AbstractFactory { @Override public Engine createEngine() { return new EngineB(); } @Override public Aircondition createAircondition() { return new AirconditionB(); } } /** * 抽象工厂模式 * @author cdzhujun * */ public class FactoryPatternDemo3 { public static void main(String[] args){ //生产宝马320系列配件 FactoryBMW320_2 factoryBMW320 = new FactoryBMW320_2(); factoryBMW320.createEngine(); factoryBMW320.createAircondition(); //生产宝马523系列配件 FactoryBMW523_2 factoryBMW523 = new FactoryBMW523_2(); factoryBMW523.createEngine(); factoryBMW523.createAircondition(); } }
执行结果:
制造-->EngineA 制造-->AirconditionA 制造-->EngineB 制造-->AirconditionB
策略模式:
与工厂模式的区别:工厂模式是创建型模式(负责new),策略模式是行为性模式(负责提供不同方案,行为)例子:
interface MemberStrategy { /** * 计算图书的价格 * @param booksPrice 图书的原价 * @return 计算出打折后的价格 */ public double calcPrice(double booksPrice); } class PrimaryMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("对于初级会员的没有折扣"); return booksPrice; } } class IntermediateMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("对于中级会员的折扣为10%"); return booksPrice * 0.9; } } class AdvancedMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("对于高级会员的折扣为20%"); return booksPrice * 0.8; } } class Price { // 持有一个具体的策略对象 private MemberStrategy strategy; /** * 构造函数,传入一个具体的策略对象 * @param strategy 具体的策略对象 */ public Price(MemberStrategy strategy) { this.strategy = strategy; } /** * 计算图书的价格 * @param booksPrice 图书的原价 * @return 计算出打折后的价格 */ public double quote(double booksPrice) { return this.strategy.calcPrice(booksPrice); } } public class StrategyPatternDemo { public static void main(String[] args) { // 选择并创建需要使用的策略对象 MemberStrategy strategy = new AdvancedMemberStrategy(); // 创建环境 Price price = new Price(strategy); // 计算价格 double quote = price.quote(300); System.out.println("图书的最终价格为:" + quote); } }
执行结果:
对于高级会员的折扣为20% 图书的最终价格为:240.0
代理模式:
代理类的作用是在真实的操作之外,如果还需要加一些处理操作,又不改动原操作的情况下,即可使用代理模式。例子:
interface Network { // 定义Network接口 public void browse(); // 定义浏览的抽象方法 } class Real implements Network { // 真实的上网操作 public void browse() { // 覆写抽象方法 System.out.println("上网浏览信息!"); } } /** * 代理类的作用是在真实的操作之外,如果还需要加一些处理操作,又不改动原操作的情况下,即可使用代理模式 * @author cdzhujun * */ class Proxy implements Network { // 代理上网 private Network network; public Proxy(Network network) {// 设置代理的真实操作 this.network = network; // 设置代理的子类 } public void check() { // 身份验证操作 System.out.println("检查用户是否合法!"); } public void browse() { this.check(); // 调用具体的代理业务操作 this.network.browse(); // 调用真实的上网操作 } } public class ProxyDemo { public static void main(String args[]) { Network net = null; // 定义接口对象 net = new Proxy(new Real()); // 实例化代理,同时传入代理的真实操作 net.browse(); // 调用代理的上网操作 } }
执行结果:
检查用户是否合法! 上网浏览信息!
观察者模式:
观察者模式的应用场景:
1、对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
观察者模式的优点:
1、 Subject和Observer之间是松偶合的,分别可以各自独立改变。
2、 Subject在发送广播通知的时候,无须指定具体的Observer,Observer可以自己决定是否要订阅Subject的通知。
3、遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
观察者模式的缺陷:
1、松偶合导致代码关系不明显,有时可能难以理解。
2、如果一个Subject被大量Observer订阅的话,在广播通知的时候可能会有效率问题。(毕竟只是简单的遍历)
例子:
import java.util.ArrayList; import java.util.List; interface Subject { //添加观察者 void addObserver(Observer obj); //移除观察者 void deleteObserver(Observer obj); //当主题方法改变时,这个方法被调用,通知所有的观察者 void notifyObserver(); } interface Observer { //当主题状态改变时,会将一个String类型字符传入该方法的参数,每个观察者都需要实现该方法 public void update(String info); } class TeacherSubject implements Subject { //用来存放和记录观察者 private List<Observer> observers=new ArrayList<Observer>(); //记录状态的字符串 private String info; @Override public void addObserver(Observer obj) { observers.add(obj); } @Override public void deleteObserver(Observer obj) { int i = observers.indexOf(obj); if(i>=0){ observers.remove(obj); } } @Override public void notifyObserver() { for(int i=0;i<observers.size();i++){ Observer o=(Observer)observers.get(i); o.update(info); } } //布置作业的方法,在方法最后,需要调用notifyObserver()方法,通知所有观察者更新状态 public void setHomework(String info){ this.info=info; System.out.println("今天的作业是"+info); this.notifyObserver(); } } class StudentObserver implements Observer { //保存一个Subject的引用,以后如果可以想取消订阅,有了这个引用会比较方便 private TeacherSubject t; //学生的姓名,用来标识不同的学生对象 private String name; //构造器用来注册观察者 public StudentObserver(String name,TeacherSubject t) { this.name=name; this.t = t; //每新建一个学生对象,默认添加到观察者的行列 t.addObserver(this); } @Override public void update(String info) { System.out.println(name+"得到作业:"+info); } } /** * 演示观察者模式 * @author cdzhujun */ public class TestObserver { public static void main(String[] args) { TeacherSubject teacher = new TeacherSubject(); StudentObserver zhangSan=new StudentObserver("张三", teacher); StudentObserver LiSi=new StudentObserver("李四", teacher); StudentObserver WangWu=new StudentObserver("王五", teacher); teacher.setHomework("第二页第六题"); teacher.setHomework("第三页第七题"); teacher.setHomework("第五页第八题"); } }
执行结果:
今天的作业是第二页第六题 张三得到作业:第二页第六题 李四得到作业:第二页第六题 王五得到作业:第二页第六题 今天的作业是第三页第七题 张三得到作业:第三页第七题 李四得到作业:第三页第七题 王五得到作业:第三页第七题 今天的作业是第五页第八题 张三得到作业:第五页第八题 李四得到作业:第五页第八题 王五得到作业:第五页第八题