常用设计模式
一、单例模式:
1、只能有一个实例;2、单例类必须自己创建自己的实例;3、单例必须给所有对象提供这一实例。
1)、懒汉式(延迟加载,用到时才加载):
优点:延迟加载(需要的时候才去加载),适合单线程操作
缺点: 线程不安全,在多线程中很容易出现不同步的情况,如在数据库对象进行的频繁读写操作时。
1 /** 2 * 懒汉式 3 * 4 * 优点:延迟加载(需要的时候才去加载),适合单线程操作 5 缺点: 线程不安全,在多线程中很容易出现不同步的情况,如在数据库对象进行的频繁读写操作时。 6 * 7 * @author admin 8 * 9 */ 10 public class Singleton { 11 12 private static Singleton obj = null; 13 14 // 私有构造方法,防止被实例化 15 private Singleton() { 16 } 17 18 19 public static Singleton getSingleton() { 20 if (obj == null) { 21 obj = new Singleton(); 22 } 23 return obj; 24 } 25 }
2)、饿汉式(立即加载,自行new,向外提供):
优点:线程安全
1 /** 2 * 饿汉式单例模式 3 * 1、构造器私有 4 * 2、自行创建 5 * 3、向外提供这个实例 6 * 4、强调这是一个单例用关键字final 7 * 8 * 9 * @author admin 10 * 11 */ 12 public class Singleton2 { 13 14 private static Singleton2 instance = new Singleton2(); 15 private Singleton2(){} 16 }
二、工厂模式
1、简单工厂模式:简单工厂模式是属于创建型模式,又叫做静态工厂方法,不属于23种GOF设计模式之一。可以理解为是不同工厂模式的一个特殊实现。
例如:抽象一个面条基类,(接口也可以),这是产品的抽象类。
1 public abstract class INoodles { 2 /** 3 * 描述每种面条啥样的 4 */ 5 public abstract void desc(); 6 }
先来一份兰州拉面(具体的产品类):
1 public class LzNoodles extends INoodles { 2 @Override 3 public void desc() { 4 System.out.println("兰州拉面 上海的好贵 家里才5 6块钱一碗"); 5 } 6 }
程序员加班必备也要吃泡面(具体的产品类):
1 public class PaoNoodles extends INoodles { 2 @Override 3 public void desc() { 4 System.out.println("泡面好吃 可不要贪杯"); 5 } 6 }
还有我最爱吃的家乡的干扣面(具体的产品类):
1 public class GankouNoodles extends INoodles { 2 @Override 3 public void desc() { 4 System.out.println("还是家里的干扣面好吃 6块一碗"); 5 } 6 }
准备工作做完了,我们来到一家“简单面馆”(简单工厂类),菜单如下:
1 public class SimpleNoodlesFactory { 2 public static final int TYPE_LZ = 1;//兰州拉面 3 public static final int TYPE_PM = 2;//泡面 4 public static final int TYPE_GK = 3;//干扣面 5 6 public static INoodles createNoodles(int type) { 7 switch (type) { 8 case TYPE_LZ: 9 return new LzNoodles(); 10 case TYPE_PM: 11 return new PaoNoodles(); 12 case TYPE_GK: 13 default: 14 return new GankouNoodles(); 15 } 16 } 17 }
简单面馆就提供三种面条(产品),你说你要啥,他就给你啥。这里我点了一份干扣面:
1 /** 2 * 简单工厂模式 3 */ 4 INoodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_GK); 5 noodles.desc();
2、工厂方法模式:
在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
工厂:
1 package com.demoFound.factoryMethod.factory; 2 3 import com.demoFound.factoryMethod.message.IMyMessage; 4 5 /** 6 * 工厂方法模式_工厂接口 7 * 8 * @author popkidorc 9 * 10 */ 11 public interface IMyMessageFactory { 12 13 public IMyMessage createMessage(String messageType); 14 }
1 package com.demoFound.factoryMethod.factory; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import com.demoFound.factoryMethod.message.IMyMessage; 7 import com.demoFound.factoryMethod.message.MyMessageEmail; 8 import com.demoFound.factoryMethod.message.MyMessageOaTodo; 9 import com.demoFound.factoryMethod.message.MyMessageSms; 10 11 /** 12 * 工厂方法模式_工厂实现 13 * 14 * @author popkidorc 15 * 16 */ 17 public class MyMessageFactory implements IMyMessageFactory { 18 19 @Override 20 public IMyMessage createMessage(String messageType) { 21 // 这里的方式是:消费者知道自己想要什么产品;若生产何种产品完全由工厂决定,则这里不应该传入控制生产的参数。 22 IMyMessage myMessage; 23 Map<String, Object> messageParam = new HashMap<String, Object>(); 24 // 根据某些条件去选择究竟创建哪一个具体的实现对象,条件可以传入的,也可以从其它途径获取。 25 // sms 26 if ("SMS".equals(messageType)) { 27 myMessage = new MyMessageSms(); 28 messageParam.put("PHONENUM", "123456789"); 29 } else 30 // OA待办 31 if ("OA".equals(messageType)) { 32 myMessage = new MyMessageOaTodo(); 33 messageParam.put("OAUSERNAME", "testUser"); 34 } else 35 // email 36 if ("EMAIL".equals(messageType)) { 37 myMessage = new MyMessageEmail(); 38 messageParam.put("EMAIL", "test@test.com"); 39 } else 40 // 默认生产email这个产品 41 { 42 myMessage = new MyMessageEmail(); 43 messageParam.put("EMAIL", "test@test.com"); 44 } 45 myMessage.setMessageParam(messageParam); 46 return myMessage; 47 } 48 }
产品:
1 package com.demoFound.factoryMethod.message; 2 3 import java.util.Map; 4 5 /** 6 * 工厂方法模式_产品接口 7 * 8 * @author popkidorc 9 * 10 */ 11 public interface IMyMessage { 12 13 public Map<String, Object> getMessageParam(); 14 15 public void setMessageParam(Map<String, Object> messageParam); 16 17 public void sendMesage() throws Exception;// 发送通知/消息 18 19 }
1 package com.demoFound.factoryMethod.message; 2 3 import java.util.Map; 4 5 /** 6 * 工厂方法模式_虚拟产品类 7 * 8 * @author popkidorc 9 * 10 */ 11 public abstract class MyAbstractMessage implements IMyMessage { 12 13 private Map<String, Object> messageParam;// 这里可以理解为生产产品所需要的原材料库。最好是个自定义的对象,这里为了不引起误解使用Map。 14 15 @Override 16 public Map<String, Object> getMessageParam() { 17 return messageParam; 18 } 19 20 @Override 21 public void setMessageParam(Map<String, Object> messageParam) { 22 this.messageParam = messageParam; 23 } 24 }
1 package com.demoFound.factoryMethod.message; 2 3 /** 4 * 工厂方法模式_oa待办产品 5 * 6 * @author popkidorc 7 * 8 */ 9 public class MyMessageOaTodo extends MyAbstractMessage { 10 11 @Override 12 public void sendMesage() throws Exception { 13 // TODO Auto-generated method stub 14 if (null == getMessageParam() 15 || null == getMessageParam().get("OAUSERNAME") 16 || "".equals(getMessageParam().get("OAUSERNAME"))) { 17 throw new Exception("发送OA待办,需要传入OAUSERNAME参数");// 为了简单起见异常也不自定义了 18 }// 这里的参数需求就比较多了不一一处理了 19 20 System.out 21 .println("我是OA待办,发送通知给" + getMessageParam().get("OAUSERNAME")); 22 } 23 24 }
1 package com.demoFound.factoryMethod.message; 2 3 /** 4 * 工厂方法模式_sms产品 5 * 6 * @author popkidorc 7 * 8 */ 9 public class MyMessageSms extends MyAbstractMessage { 10 11 @Override 12 public void sendMesage() throws Exception { 13 // TODO Auto-generated method stub 14 if (null == getMessageParam() 15 || null == getMessageParam().get("PHONENUM") 16 || "".equals(getMessageParam().get("PHONENUM"))) { 17 throw new Exception("发送短信,需要传入PHONENUM参数");// 为了简单起见异常也不自定义了 18 }// 另外短信信息,以及其他各种协议参数等等都要处理 19 20 System.out.println("我是短信,发送通知给" + getMessageParam().get("PHONENUM")); 21 } 22 23 }
消费者:
1 package com.demoFound.factoryMethod; 2 3 import com.demoFound.factoryMethod.factory.IMyMessageFactory; 4 import com.demoFound.factoryMethod.factory.MyMessageFactory; 5 import com.demoFound.factoryMethod.message.IMyMessage; 6 7 /** 8 * 工厂方法模式_消费者类 9 * 10 * @author popkidorc 11 * 12 */ 13 public class MyFactoryMethodMain { 14 15 public static void main(String[] args) { 16 IMyMessageFactory myMessageFactory = new MyMessageFactory(); 17 IMyMessage myMessage; 18 // 对于这个消费者来说,不用知道如何生产message这个产品,耦合度降低 19 try { 20 // 先来一个短信通知 21 myMessage = myMessageFactory.createMessage("SMS"); 22 myMessage.sendMesage(); 23 24 // 来一个oa待办 25 myMessage = myMessageFactory.createMessage("OA"); 26 myMessage.sendMesage(); 27 28 // 来一个邮件通知 29 myMessage = myMessageFactory.createMessage("EMAIL"); 30 myMessage.sendMesage(); 31 } catch (Exception e) { 32 e.printStackTrace(); 33 } 34 } 35 }
3、抽象工厂模式
定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
抽象工厂模式与工厂方法模式的区别:抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象
例如:
1 interface IProduct1 { 2 public void show(); 3 } 4 interface IProduct2 { 5 public void show(); 6 } 7 8 class Product1 implements IProduct1 { 9 public void show() { 10 System.out.println("这是1型产品"); 11 } 12 } 13 class Product2 implements IProduct2 { 14 public void show() { 15 System.out.println("这是2型产品"); 16 } 17 } 18 19 interface IFactory { 20 public IProduct1 createProduct1(); 21 public IProduct2 createProduct2(); 22 } 23 class Factory implements IFactory{ 24 public IProduct1 createProduct1() { 25 return new Product1(); 26 } 27 public IProduct2 createProduct2() { 28 return new Product2(); 29 } 30 } 31 32 public class Client { 33 public static void main(String[] args){ 34 IFactory factory = new Factory(); 35 factory.createProduct1().show(); 36 factory.createProduct2().show(); 37 } 38 }
又如;
1 package ppp; 2 3 //Person接口定义 4 public interface Person { 5 public String sayHello(String name); 6 public String sayGoodbye(String name); 7 }
1 package ppp; 2 //American类实现Person接口 3 public class American implements Person { 4 public String sayHello(String name){ 5 return name+",hello"; 6 } 7 public String sayGoodbye(String name) 8 { 9 return name+",goodbye"; 10 } 11 }
1 package ppp; 2 //Chinese类实现Person接口 3 public class Chinese implements Person { 4 public String sayHello(String name){ 5 return name+",您好"; 6 } 7 public String sayGoodbye(String name) 8 { 9 return name+",下次再见"; 10 } 11 }
1 package ppp; 2 3 public class PersonFactory { 4 public Person getPerson(String ethnic) 5 { 6 if(ethnic.equalsIgnoreCase("chin")) 7 { 8 return new Chinese(); 9 }else{ 10 return new American(); 11 } 12 } 13 }
1 package ppp; 2 3 public class FactoryTest { 4 public static void main(String[] args){ 5 //创建PersonFactory实例 ,获得工厂实例 6 PersonFactory pf = new PersonFactory(); 7 //定义接口Person实例,面向接口编程 8 Person p = null; 9 //使用工厂获得person实例 10 p = pf.getPerson("chin"); 11 //下面调用Person接口方法 12 System.out.println(p.sayHello("wawa")); 13 System.out.println(p.sayGoodbye("wawa")); 14 //使用工厂获得Person的另一个实例 15 p = pf.getPerson("ame"); 16 //再次调用Person接口的方法 17 System.out.println(p.sayHello("wawa")); 18 System.out.println(p.sayGoodbye("wawa")); 19 } 20 }
sping中的单例和工厂模式:
spring就是一个最大的工厂,例如,Spring使用配置文件管理所有的Bean,其配置文件中的Bean由Spring工厂负责生成和管理,既使没有bean的工厂类,程序依然可以使用工厂模式,因为Sping就是工厂。