浅谈设计模式(一)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
之前读过几本设计模式的书籍比如设计模式之禅,大概都是介绍设计模式模型。最开始读的时候感觉设计模式这块的知识好抽象,23种设计模式一点点去啃去记感觉好难
最近重新学习了设计模式有了新的理解
提示:以下是本篇文章正文内容,下面案例可供参考
一、单例模式Singleton
说到单例模式大家都很了解了什么懒汉式单例模式饿汉式单例模式。这些个名词之前是困扰我的一大原因之一,因为过于注意这些名词导致我忽略了对代码的理解。
今天再说起单例模式的时候让我们忘记这些名词来感受一下代码本身,会有更深入的理解。
对于单例模式的应用场景是必须要提到的,常用的场景就是各种工厂类对象,Manager对象或者连接池因为这些个对象在类加载的时候只需要实例化一次即可,这也
是单例模式设计的初衷,接下来就让我们看看单例模式的各种写法和优缺点
1.俗称的饿汉式单例(最常用的单例模式写法虽然不完美但是问题无伤大雅)
直接贴代码
也可以通过静态块的方式实例化对象
private static Msg01 INSTANCE; //静态的实例域
static {
INSTANCE=new Msg01();
}
这种模式是我们常用的单例模式写法,其中的缺点就是有些人认为这样写会造成虚拟机在类加载的时候就会实例化对象,这样不管用不用都会产生对象(个人认为这种是可以接受的)
为了解决这个问题就产生了懒汉式单例模式
2.懒汉式单例模式
由通过判断INSTANCE对象来决定是否实例化,这样就在多线程访问的时候会导致生成多个对象,虽然解决了实例化对象的问题但是引起了更糟糕的状况,线程不安全
了。所以我们要在方法上加锁 public static synchronized Msg05 getInstance(){} 这样又会导致效率大大降低,所以我们又要引入双重判断加入同步代码块来解决效率问题
//此处判断是造成多线程非单例问题的地方
if(INSTANCE==null){
synchronized(Msg02.class){
if(INSTANCE==null){
try {
Thread.sleep(2);
}catch (Exception e){
}
INSTANCE=new Msg05();
}
}
}
对于第一种饿汉式单例模式解决方案还有一种方法就是引入静态内部类的方式,是可以避免对象实例化的问题 以为外部类在加载的时候是不会实例化静态内部类的而且内部类
也会隐藏起来不被外部访问到以确保对象的唯一
3.静态内部类饿汉式
完美解决实例化对象问题还不会造成现成不安全
当然还有一种解决方式
4.枚举单例
枚举单例的优势在于枚举类是没有构造器的所以可以有效避免被反序列化
二、策略模式Strategy
策略模式封装的是做一件事情不同的执行方式,最典型的应用是我们在进行排序的时候用到的比较器Comparator接口,例如我们要对一个数组进行排序。
如果不使用策略模式,当定义一个排序方法public void sort(int[] a) 对整型进行排序、public void sort(float[] a) 对浮点型进行排序等等我们需要对sort方法进行
重载甚至修改,本着对修改关闭对扩展开放的开闭原则我们要对程序进行改造所以就要应用到策略模式如果我们现在需要一个通过猫的重量对猫进行排序该
怎么办呢应用到策略模式首先要定义比较器接口Comrarable<T> 并定义一个规则方法 int compare(T o1,T o2),然后定义一个猫的实体,有重量属性weight
然后定义一个CatComparator 接口定义比较方式,
然后建立一个Sorter类 定义排序的方法
最后在客户端传入比较器进行排序
Cat[] cat={new Cat(9),new Cat(4),new Cat(5)};
Sorter sort=new Sorter<Cat>();
sort.sort(cat,new CatComparator());
System.out.println(Arrays.toString(cat));
这样可以很好的扩展不通的排序方法这就是策略模式,最后是策略模式的类图
三、工厂系列Factory
凡是能产生对象,方法都可以称之为工厂。工厂设计模式分为工厂方法和抽象工厂,简单来说工厂方法模式可以在产品维度进行很好的扩展。而抽象工厂可以在产品一族维度进行
很好的扩展。
比如,我们现在要定制交通工具,飞机,火车,汽车等等,最简单的我们可以考虑使用简单工厂模式进行扩展定义一个交通工具的工厂VehicleFactory,分别有creatCar,creatPlane,creatTrain三个方法。方法返回值为new 出来的对象。这样就可以实现一个简单工厂的模式,但是这样扩展性实在是太差了。如果有了新的交通工具还需要添加方法。接下来我们重新定义一个Vehicle类定义一个方法 go(交通工具都可以移动),然后定义一个VehicleFactory里面有一个creatVehicle,返回值为Vehicle。接下来具体的交通工具都继承至Vehicle这样就可以对产品进行扩展这个就是我们说的工厂方法模式。
现在我们的需求又增加了,我们在开车的时候需要吃东西(虽然现实不允许哈哈我们暂且拿他举例子),还需要使用武器进行射击。那么车,食品,武器就是一个产品族。如果在魔法世界我们可以骑扫帚吃蘑菇使用魔法棒攻击,这个时候就需要我们对产品族进行很好的扩展。我们来想一下怎么实现。首先定义三个抽象类(具体是定义抽象类还是接口我们一般总结为形容词用接口定义名词用抽象类定义),食品,武器,和交通工具。Food,Weapon,Vehicle。三个类中定义一个抽象方法print方法进行输出。然后定义一个抽象工厂类VehicleFactory,定一个抽象方法creat,然后在creat方法里面创建出对应的Food,Weapon,Vehicle对象并调用他们的print方法。这样我们在客户端调用的时候就可以用工厂子类去扩展VehicleFactory,是现实工厂还是魔法工厂或者火星工厂,然后在具体的工厂里实现用的是什么交通工具,吃的是什么食物用的武器等等。这样就是抽象工厂模式可以对产品族进行很好的扩展。
四、Facade门面-Mediator调停者
接下来介绍两个比较类似的模式门面和调停者,这两个模式解决的问题是解耦。举个例子我们在去政府部门办事儿的时候有时候办一件事需要去好多地方办理,这时候我们多么希望有一个门面跟我们对接替我们协调内部的所有事情,这个封装内部逻辑的类就叫做门面模式,有了他的存在我们再也不用关心内部的负责的逻辑只需要访问提供的接口即可,如果有了新的逻辑加入只需要改动内部即可不需要把新增的同其他所有的在进行联系
与其相似的是调停者模式,他是解耦内部复杂逻辑的,在门面进行协调的时候他们的内部还是存在好多部门,部门之间的联系也是很紧密的,如果增加一个新的部门还要跟其他所以部门进行联系,这时候我们需要一个调停者对部门之间进行协调。最好的例子就是消息中间件的应用,所有部门有消息扔进消息中间件,其他部门想用再去中间件里面去取即可,有效解耦
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。