zoukankan      html  css  js  c++  java
  • 设计模式——创建型模式

    学习一个设计模式,至少应该明白,这种设计模式要解决什么问题,什么时候可以使用,他是如何解决问题的,要记住关键代码,还有优缺点是什么。

    创建型模式

    创建型模式顾名思义,就是用来创建对象的。有时候为了保证创建的对象唯一,或者创建的高效等等,就需要用到这些设计模式。

    单例模式

    单例模式就是保证创建的对象是唯一的,实现方式并不唯一,下面会考虑多线程环境下的实现。
    然后单例模式有三个要点:

    1. 某个类只能有一个实例。
    2. 它必须自行创建这个类的实例。
    3. 它必须自行向整个系统提供这个实例。

    下面是非多线程情况下的单例模式(最简单的实现方式)——任务管理器的实现

    class TaskManager{
        private static TaskManager tm = null;
        private TaskManager(){...}
        public void displayProcesses(){...}
        public void displayService(){...}
    
        public static TaskManager getInstance(){
            if(tm == null){
                tm = new TaskManager();
            }
            retrun tm;
        }
    }
    

    上述代码中,tm实例和初始化方法无法被外界访问(也就是不能被new),外界只能通过调用getInstance方法去获取这个类的实例,那么为什么实例必须是static的呢?(tm)

    1. 通过静态的类方法(getInstance) 获取instance,该方法是静态方法,instance由该方法返回(被该方法使用),如果instance非静态,无法被getInstance调用;
    2. instance需要在调用getInstance时候被初始化,只有static的成员才能在没有创建对象时进行初始化。且类的静态成员在类第一次被使用时初始化后就不会再被初始化,保证了单例。(最主要的原因)
    3. static类型的instance存在静态存储区,每次调用时,都指向的同一个对象。

    下面我们考虑多线程情况下的单例模式,饿汉单例模式和懒汉单例模式。

    饿汉单例模式

    饿汉单例模式能保证在多线程情况下的对象唯一性,那他是怎么实现的呢?
    最关键的一点,是他在类加载的时候就创建好了对象,这样就保证对象已经存在。

    class EagerSingleton{
        private static finale EagerSingleton = new EagerSingleton();
        private EagerSingleton(){}
        public static EagerSingleton getInstance(){
            return instance;
        }
    }
    

    懒汉单例模式

    懒汉单例模式用到了一种技术叫做延迟加载技术(Lazy Load),即类加载时并不自行实例化,需要的时候再加载实例,为了避免多个线程同时调用getInstance(),可以使用关键字synchronized,另外可以通过对代码块进行同步,而不是对这个getInstance方法同步来优化。

    简单工厂模式

    首先要说明的是,工厂方法模式是最常用的创建模式,简单工厂模式是工厂方法模式的基础。直接放代码:

    package CreatePartten;
    
    /**
     * Created by Lettino on 2018/11/12
     */
    interface Chart {
        public void display();
    }
    
    class HistogramChart implements Chart {
        public HistogramChart() {
            System.out.println("创建柱状图");
        }
    
        public void display() {
            System.out.println("创建柱状图");
        }
    }
    
    class PieChart implements Chart {
        public PieChart() {
            System.out.println("创建饼图");
        }
    
        public void display() {
            System.out.println("创建饼图");
        }
    }
    
    class LineChart implements Chart {
        public LineChart() {
            System.out.println("创建折线图");
        }
    
        public void display() {
            System.out.println("创建折线图");
        }
    }
    
    public class ChartFactory {
        public static Chart getChart(String type) {
            Chart chart = null;
            if (type.equalsIgnoreCase("histogram")) {
                chart = new HistogramChart();
                System.out.println("初始化设置柱状图");
            } else if (type.equalsIgnoreCase("pie")) {
                chart = new PieChart();
                System.out.println("初始化设置饼图");
            } else if (type.equalsIgnoreCase("line")) {
                chart = new LineChart();
                System.out.println("初始化设置折线图");
            }
            return chart;
        }
    }
    

    优点:

    1. 这个时候,只需要客户端调用ChartFactory就可以创建对应的类了,而且客户端并不需要知道创建的过程,降低了耦合性,如果需要更换产品,只需要修改传入的参数即可。
    2. 另外还可以通过XML将参数提取出来,这样就可以只修改配置文件来创建需要创建的对象。

    缺点:

    1. 这个简单工厂类中集合了所有产品的创建逻辑,指责过大,一旦这个类出现问题,所有的类的不能创建。
    2. 扩展比较困难,每次扩展需要修改工厂类,这个违背开闭原则,如果产品类型过多,会造成工厂逻辑过于复杂。
    3. 简单工厂使用了静态工厂方法,造成工厂角色无法形成继承的等级结构。

    使用场景

    1. 工厂类负责创建的对象比较少,不会造成工厂类中的业务逻辑太过复杂。
    2. 客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

    工厂方法模式

    工厂方法模式中包含四个角色:

    1. Product(抽象产品) 他是定义产品的借口,是工厂方法模式锁创建对象的超类型,也是产品对象的公共父类。
    2. ConcreteProduct(具体产品) 它实现了抽象产品借口,某种类型的具体产品由专门的具体工厂创建,具体工厂和具体产品之间一一对应。
    3. Factory(抽象工厂) 在抽象工厂类,声明了工厂方法(Factory Method)用于返回一个产品。抽象工厂是工厂方法模式的核心,所有创建对象的工厂类都必须实现该接口。
    4. ConcreteFactory(具体工厂) 他是具体工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端,返回一个具体产品类的实例。
      与简单工厂模式相比,工厂方法模式最重要的区别是引入了抽象工厂角色,抽象工厂可以是接口,也可以是抽象类或者具体类。

    抽象工厂模式

  • 相关阅读:
    简版一致性hash算法实现
    js类型转换问题
    VIVADO 2017.4配置MIG IP注意事项
    工作笔记2
    工作笔记1
    spring5 + hibernate5(redisson二级缓存) + JPA + JTA + ActiveMQ(JMS)
    spring data jpa 缓存(hibernate)
    JPA @Temporal
    C++ RTTI
    二叉树遍历方法总结
  • 原文地址:https://www.cnblogs.com/zhoujiayong/p/10141665.html
Copyright © 2011-2022 走看看