首页 > 其他 > 详细

创建型设计模式

时间:2020-07-02 11:37:04      阅读:45      评论:0      收藏:0      [点我收藏+]

1、工厂方法模式

1-1 普通工厂模式

举例如下:(我们举一个发送邮件和短信的例子)

首先,创建二者的共同接口:

1     public interface Sender {  
2         public void Send();  
3     }  

其次,创建实现类:

1     public class MailSender implements Sender {  
2         @Override  
3         public void Send() {  
4             System.out.println("this is mailsender!");  
5         }  
6     }  
1     public class SmsSender implements Sender {  
2       
3         @Override  
4         public void Send() {  
5             System.out.println("this is sms sender!");  
6         }  
7     }  

 

最后,建工厂类:

 1     public class SendFactory {  
 2       
 3         public Sender produce(String type) {  
 4             if ("mail".equals(type)) {  
 5                 return new MailSender();  
 6             } else if ("sms".equals(type)) {  
 7                 return new SmsSender();  
 8             } else {  
 9                 System.out.println("请输入正确的类型!");  
10                 return null;  
11             }  
12         }  
13     }  

 

我们来测试下:

    public class FactoryTest {  
      
        public static void main(String[] args) {  
            SendFactory factory = new SendFactory();  
            Sender sender = factory.produce("sms");  
            sender.Send();  
        }  
    }  

 

输出:this is sms sender!

 

1-2 多个工厂方法模式

将上面的代码做下修改,改动下SendFactory类就行,如下:

 1 public class SendFactory {  
 2        public Sender produceMail(){  
 3 
 4             return new MailSender();  
 5         }  
 6           
 7         public Sender produceSms(){  
 8             return new SmsSender();  
 9         }  
10 }  

 

测试类如下:

1     public class FactoryTest {  
2       
3         public static void main(String[] args) {  
4             SendFactory factory = new SendFactory();  
5             Sender sender = factory.produceMail();  
6             sender.Send();  
7         }  
8     }  

输出:this is mailsender!

1-3、静态工厂方法模式

将上面的多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

 1     public class SendFactory {  
 2           
 3         public static Sender produceMail(){  
 4             return new MailSender();  
 5         }  
 6           
 7         public static Sender produceSms(){  
 8             return new SmsSender();  
 9         }  
10     }  
1     public class FactoryTest {  
2       
3         public static void main(String[] args) {      
4             Sender sender = SendFactory.produceMail();  
5             sender.Send();  
6         }  
7     }  

输出:this is mailsender!

 

2、抽象工厂模式

1     public interface Sender {  
2         public void Send();  
3     }  

 

两个实现类:

1     public class MailSender implements Sender {  
2         @Override  
3         public void Send() {  
4             System.out.println("this is mailsender!");  
5         }  
6     }  
1 public class SmsSender implements Sender {  
2   
3     @Override  
4     public void Send() {  
5         System.out.println("this is sms sender!");  
6     }  
7 } 

 

两个工厂类:

1     public class SendMailFactory implements Provider {  
2           
3         @Override  
4         public Sender produce(){  
5             return new MailSender();  
6         }  
7     }  
1 public class SendSmsFactory implements Provider{  
2   
3     @Override  
4     public Sender produce() {  
5         return new SmsSender();  
6     }  
7 } 

在提供一个接口:

1 public interface Provider {  
2     public Sender produce();  
3 } 

测试类:

1     public class Test {  
2       
3         public static void main(String[] args) {  
4             Provider provider = new SendMailFactory();  
5             Sender sender = provider.produce();  
6             sender.Send();  
7         }  
8     } 

 

Spring中工厂设计模式的使用

Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。

两者对比:

  • BeanFactory :延迟注入(使用到某个 bean 的时候才会注入),相比于BeanFactory来说会占用更少的内存,程序启动速度更快。
  • ApplicationContext :容器启动的时候,不管你用没用到,一次性创建所有 bean 。BeanFactory 仅提供了最基本的依赖注入支持,ApplicationContext 扩展了 BeanFactory ,除了有BeanFactory的功能之外还有额外更多功能,所以一般开发人员使用ApplicationContext会更多。

ApplicationContext的三个实现类:

  1. ClassPathXmlApplication:把上下文文件当成类路径资源。
  2. FileSystemXmlApplication:从文件系统中的 XML 文件载入上下文定义信息。
  3. XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息。

Example:

 1 import org.springframework.context.ApplicationContext;
 2 import org.springframework.context.support.FileSystemXmlApplicationContext;
 3 
 4 public class App {
 5     public static void main(String[] args) {
 6         ApplicationContext context = new FileSystemXmlApplicationContext(
 7                 "C:/work/IOC Containers/springframework.applicationcontext/src/main/resources/bean-factory-config.xml");
 8 
 9         HelloApplicationContext obj = (HelloApplicationContext) context.getBean("helloApplicationContext");
10         obj.getMsg();
11     }
12 }

 

3、单例模式

首先我们写一个简单的单例类:

 1     public class Singleton {  
 2       
 3         /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */  
 4         private static Singleton instance = null;  
 5       
 6         /* 私有构造方法,防止被实例化 */  
 7         private Singleton() {  
 8         }  
 9       
10         /* 静态工程方法,创建实例 */  
11         public static Singleton getInstance() {  
12             if (instance == null) {  
13                 instance = new Singleton();  
14             }  
15             return instance;  
16         }  
17       
18     }  

这个类可以满足基本要求,但是,像这样毫无线程安全保护的类,如果我们把它放入多线程的环境下,肯定就会出现问题了,如何解决?我们首先会想到对getInstance方法加synchronized关键字,如下:

1     public static synchronized Singleton getInstance() {  
2             if (instance == null) {  
3                 instance = new Singleton();  
4             }  
5             return instance;  
6         }  

但是,synchronized关键字锁住的是这个对象,这样的用法,在性能上会有所下降,因为每次调用getInstance(),都要对对象上锁,事实上,只有在第一次创建对象的时候需要加锁,之后就不需要了,所以,这个地方需要改进。我们改成下面这个:

 1     public static Singleton getInstance() {  
 2             if (instance == null) {  
 3                 synchronized (instance) {  
 4                     if (instance == null) {  
 5                         instance = new Singleton();  
 6                     }  
 7                 }  
 8             }  
 9             return instance;  
10         }  
单例模式使用内部类来维护单例的实现,JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的。这样当我们第一次调用getInstance的时候,JVM能够帮我们保证instance只被创建一次,并且会保证把赋值给instance的内存初始化完毕。同时该方法也只会在第一次调用的时候使用互斥机制,这样就解决了低性能问题。
 1     public class Singleton {  
 2       
 3         /* 私有构造方法,防止被实例化 */  
 4         private Singleton() {  
 5         }  
 6       
 7         /* 此处使用一个内部类来维护单例 */  
 8         private static class SingletonFactory {  
 9             private static Singleton instance = new Singleton();  
10         }  
11       
12         /* 获取实例 */  
13         public static Singleton getInstance() {  
14             return SingletonFactory.instance;  
15         }  
16       
17     }  

也有人这样实现:因为我们只需要在创建类的时候进行同步,所以只要将创建和getInstance()分开,单独为创建加synchronized关键字,也是可以的:

 1     public class SingletonTest {  
 2       
 3         private static SingletonTest instance = null;  
 4       
 5         private SingletonTest() {  
 6         }  
 7       
 8         private static synchronized void syncInit() {  
 9             if (instance == null) {  
10                 instance = new SingletonTest();  
11             }  
12         }  
13       
14         public static SingletonTest getInstance() {  
15             if (instance == null) {  
16                 syncInit();  
17             }  
18             return instance;  
19         }  
20     }  
 

以上都是懒汉式单例,下面实现一个饿汉式的单例

 1     public class SingletonTest {  
 2       
 3         private static final SingletonTest instance =new SingletonTest();  
 4       
 5         private SingletonTest() {  
 6         }  
 7       
 8         public static SingletonTest getInstance() {    
 9             return instance;  
10         }  
11     }  

 

Spring中单例设计模式的使用

Spring中bean的默认作用域就是singleton(单例)的,除了singleton作用域,Spring中bean还有下面几种作用域:

  • prototype : 每次请求都会创建一个新的 bean 实例。
  • request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
  • session : 每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。
  • global-session: 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。Portlet是能够生成语义代码(例如:HTML)片段的小型Java Web插件。它们基于portlet容器,可以像servlet一样处理HTTP请求。但是,与 servlet 不同,每个 portlet 都有不同的会话

Spring实现单例的方式:

  • xml:<bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>
  • 注解:@Scope(value = "singleton")

Spring通过ConcurrentHashMap实现单例注册表的特殊方式实现单例模式。Spring实现单例的核心代码如下:

 1 // 通过 ConcurrentHashMap(线程安全) 实现单例注册表
 2 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
 3 
 4 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
 5         Assert.notNull(beanName, "‘beanName‘ must not be null");
 6         synchronized (this.singletonObjects) {
 7             // 检查缓存中是否存在实例  
 8             Object singletonObject = this.singletonObjects.get(beanName);
 9             if (singletonObject == null) {
10                 //...省略了很多代码
11                 try {
12                     singletonObject = singletonFactory.getObject();
13                 }
14                 //...省略了很多代码
15                 // 如果实例对象在不存在,我们注册到单例注册表中。
16                 addSingleton(beanName, singletonObject);
17             }
18             return (singletonObject != NULL_OBJECT ? singletonObject : null);
19         }
20     }
21     //将对象添加到单例注册表
22     protected void addSingleton(String beanName, Object singletonObject) {
23             synchronized (this.singletonObjects) {
24                 this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
25 
26             }
27         }
28 }

 

4、建造者模式

(1) 产品角色:包含多个组成部件的复杂对象。

 1     class Product{
 2         private String partA;
 3         private String partB;
 4         private String partC;
 5         public void setPartA(String partA){
 6             this.partA=partA;
 7         }
 8         public void setPartB(String partB){
 9             this.partB=partB;
10         }
11         public void setPartC(String partC) {
12             this.partC=partC;
13         }
14         public void show(){
15             //显示产品的特性
16         }
17     }

 


(2) 抽象建造者:包含创建产品各个子部件的抽象方法。

 1 abstract class Builder
 2 {
 3     //创建产品对象
 4     protected Product product=new Product();
 5     public abstract void buildPartA();
 6     public abstract void buildPartB();
 7     public abstract void buildPartC();
 8     //返回产品对象
 9     public Product getResult()
10     {
11         return product;
12     }
13 }

(3) 具体建造者:实现了抽象建造者接口。

 1 public class ConcreteBuilder extends Builder
 2 {
 3     public void buildPartA()
 4     {
 5         product.setPartA("建造 PartA");
 6     }
 7     public void buildPartB()
 8     {
 9         product.setPartA("建造 PartB");
10     }
11     public void buildPartC()
12     {
13         product.setPartA("建造 PartC");
14     }
15 }

 

(4) 指挥者:调用建造者中的方法完成复杂对象的创建。

 1 class Director
 2 {
 3     private Builder builder;
 4     public Director(Builder builder)
 5     {
 6         this.builder=builder;
 7     }
 8     //产品构建与组装方法
 9     public Product construct()
10     {
11         builder.buildPartA();
12         builder.buildPartB();
13         builder.buildPartC();
14         return builder.getResult();
15     }
16 }

 

(5) 客户类。

 1 public class Client
 2 {
 3     public static void main(String[] args)
 4     {
 5         Builder builder=new ConcreteBuilder();
 6         Director director=new Director(builder);
 7         Product product=director.construct();
 8         product.show();
 9     }
10 }

 

Spring中建造者模式的使用

spring框架,主要是用来管理对象,创建一个对象是极其复杂的,建造者模式在解析xml文件,创建BeanDefinition中发挥很大的作用。不想在这里做更细节的分析,但是可以找段代码,分析spring是如何使用它。

段落1:spring-security中解析xml

 

 

5、原型模式

 1     public class Prototype implements Cloneable, Serializable {  
 2       
 3         private static final long serialVersionUID = 1L;  
 4         private String string;  
 5       
 6         private SerializableObject obj;  
 7       
 8         /* 浅复制 */  
 9         public Object clone() throws CloneNotSupportedException {  
10             Prototype proto = (Prototype) super.clone();  
11             return proto;  
12         }  
13       
14         /* 深复制 */  
15         public Object deepClone() throws IOException, ClassNotFoundException {  
16       
17             /* 写入当前对象的二进制流 */  
18             ByteArrayOutputStream bos = new ByteArrayOutputStream();  
19             ObjectOutputStream oos = new ObjectOutputStream(bos);  
20             oos.writeObject(this);  
21       
22             /* 读出二进制流产生的新对象 */  
23             ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
24             ObjectInputStream ois = new ObjectInputStream(bis);  
25             return ois.readObject();  
26         }  
27       
28         public String getString() {  
29             return string;  
30         }  
31       
32         public void setString(String string) {  
33             this.string = string;  
34         }  
35       
36         public SerializableObject getObj() {  
37             return obj;  
38         }  
39       
40         public void setObj(SerializableObject obj) {  
41             this.obj = obj;  
42         }  
43       
44     }  
45       
46     class SerializableObject implements Serializable {  
47         private static final long serialVersionUID = 1L;  
48     }  

 Spring中原型模式的使用

 

结束。

创建型设计模式

原文:https://www.cnblogs.com/it-deepinmind/p/13223665.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!