设计模式
- 为什么写这篇文章
本人从事Java开发接近两年之久,从毕业到踏入职场得大门,准备用自己掌握得基础知识在职场创出一片天地,但理想很丰满,现实却很骨干(只能说被打击到家了,无限尬死),编码规范、整洁度、复用性无不在我得代码中丝毫未线(真的是菜到家了),但梦想岂能是这么容易就被磨灭的,从最初的揣摩大佬代码、跟读源码,由浅至深,始终加入了某种思想。。。
这里大家应该知道我要说什么了,没错,就是设计模式 这也是我一直在思考并且探究为什么要学设计模式?设计模式的优点是什么?
- 提升查看源码的能力
- 提升自己对复杂业务的逻辑的代码设计能力以及code能力
- 对面试以及后面的职场道路打下扎实的基础
比如我最近刚做了一个统一登录的需求,因为采用oauth2.0标准认证协议,有四种授权方式,要是搁以前的话,估计上去就是咔咔五个if/else,这样不足的地方就是代码臃肿,另外加入又要加入新的个性化认证,岂不是又要手改代码,这无疑从code美观上还是开放性上都显的很不友好。还好,最近刚学了工厂模式和策略模式,呼啦啦,我可不管你有哪些类型,直接一个接口整上剩下的全是弟弟,这就是设计模式的好处,可以装Bi还可以造福后人。
正文
设计模式分为创建型、结构型和行为三种类型,我们首先从创建型入手,今天就以创建型中最常用的工厂模式展开。
工厂模式主要分为三大类:
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
简单工厂模式
工厂模式主要是用于对实现逻辑的封装,并且通过对公共的接口提供对象的实列化的服务,在我添加新的类时不需大动干戈,只需要修改一点点就好。
我们以电商平台创建商品为例:
在这个简单工厂里面,如果要创建活动商品1 以及活动商品2,我们要创建商品的时候只要调用简单工厂里面的创建商品方法,根据类型创建出不同的商品然后实列化返回就可以了。
简单工厂几种实现方式:
- 静态工厂模式
我们还是以创建商品为例
package com.michstabe.designMode;
import java.math.BigDecimal;
import java.util.Objects;
/**
* @author michstabe
* @date 2022/4/21 14:16
* @description
*/
public class ProductStaticFactory {
public static Product getProduct(ProductTypeEnum type){
if(Objects.equals(type, ProductTypeEnum.one)){
return new Product("A","one",BigDecimal.valueOf(13.00));
}else if(Objects.equals(type, ProductTypeEnum.two)){
return new Product("B","two", BigDecimal.valueOf(14.01));
}else if (Objects.equals(type, ProductTypeEnum.three)){
return new Product("C", "three", BigDecimal.valueOf(15.01));
}
return null;
}
public enum ProductTypeEnum{
one,two,three;
}
public static class Product{
private String name;
private String type;
private BigDecimal money;
//getter/setter省略
public Product(String name, String type, BigDecimal money){
this.name = name;
this.type = type;
this.money = money;
}
}
}
可以发现,工厂提供一个静态方法,根据传入商品类型不同而返回不同的商品对象,并维护了一个商品类型的枚举。这种方式创建看起来其实也没什么问题,根据类型创建不同的商品,但是有一个问题不知道大家发现没有?
是不是我每增加一种类型是不是我还要去修改createProduct方法的 if else?这不是违背我们的开闭原则吗?
所以这种方式不好,我们还有接来的两种:
- 使用反射机制
- 直接注册商品对象,添加一个Type类型方法,根据type类型返回自身相同类型的方法
同样的我们还是以创建商品为列:反射实现
package com.michstabe.designMode;
import java.util.HashMap;
import java.util.Map;
/**
* @author michstabe
* @date 2022/4/21 14:34
* @description
*/
public class SimpleFactoryReflection {
private static final Map<ProductTypeEnum, Class> productMap = new HashMap<>();
public static void addProduct(ProductTypeEnum type, Class product){
productMap.put(type, product);
}
public static ProductStaticFactory.Product getProduct(ProductTypeEnum typeEnum) throws InstantiationException, IllegalAccessException {
Class aClass = productMap.get(typeEnum);
return (ProductStaticFactory.Product) aClass.newInstance();
}
public enum ProductTypeEnum{
one, two;
}
}
看上面的代码,我发现反射其实也很容易就实现了,但是在一些特定的情况下,并不适用,而且在某些特定的情况下是无法实现的,而且反射机制也会降低程序的运行效果,在对性能要求很高的场景下应该避免这种实现。
这里还有一个问题适用反射不当是容易导致线上机器出问题的,因为我们反射创建的对象属性是被SoftReference软引用的,所以当**-XX:SoftRefLRUPolicyMSPerMB** 没有设置好的话会一直让机器CPU很高。
当然他的默认值是1000,也就根据大家的情况而定吧,反正就是注意一下这点。
还有一种就是维护一个map实例,key为商品类型,value为对应类型的实例对象,这里demo就老铁们自行补充了
- 工厂方法模式
工厂方法模式是对静态工厂模式的上的一种改进,我们的工厂类直接被抽象化,需要具体特定化的逻辑代码转移到实现抽象方法的子类中,这样我们就不要再去修改工厂类(即:不用再去做什么if else 修改)这也是我们当前比较常用的一种方式。
我们还是以创建商品为例:
package com.michstabe.designMode;
import java.math.BigDecimal;
/**
* @author michstabe
* @date 2022/4/21 14:53
* @description
*/
public abstract class FactoryMethod {
protected abstract ProductStaticFactory.Product createProduct(ProductStaticFactory.ProductTypeEnum type);
public ProductStaticFactory.Product getProduct(ProductStaticFactory.ProductTypeEnum type, String name, BigDecimal money){
ProductStaticFactory.Product product = createProduct(type);
product.setName(name);
product.setMoney(money);
return product;
}
}
提供者只需要自行继承抽象工厂并且重写创建逻辑即可
这个代码大家肯定都能实现出来,但是我们真正的需要学习的是前辈们的这种工厂模式的思想。把这种思想运用到我们真实的业务场景中,学以致用才能对我们有真正的提升。
其实我们学习设计模式就是这种思想,有了这种思想 上面提到的三点优势才能体现出来对我们今后的成长,面对复杂业务设计以及思考能力才能提升。
那么问题来了,什么时候该用工厂方法模式,而非简单工厂模式呢?
这里引用设计模式之美里面的一句话:当对象的创建逻辑比较复杂,不只是简单的 new 一下就可以,而是要组合其他类对象,做各种初始化操作的时候,我们推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂。
而使用简单工厂模式,将所有的创建逻辑都放到一个工厂类中,会导致这个工厂类变得很复杂
- 抽象工厂模式
看完工厂方法模式,再理解抽象工厂模式就更加简单,因为它其实就是工厂方法的一个延伸。
工厂方法类中只有一个抽象方法,要想实现多种不同的类对象,只能去创建不同的具体工厂方法的子类来实列化,而抽象工厂 则是让一个工厂负责创建多个不同类型的对象
感觉理解起来有点绕,我们还是来画个图吧
样子可能有点丑,但是能说明问题,其实看上去可以分为以上几个部分组成:
- 抽象工厂类
- 具体工厂类
- 抽象类
抽象工厂类我个人可以理解为一个刚出厂的手机,具体抽象工厂这是认为我们每个人对这个手机壁纸自定义设置,最后抽象类我理解就是手机壁纸。
我们每个人可以自定义不同壁纸比如:动图妹妹,静图风景,小傻瓜等等。
结尾
我在几家公司任职期间,见过很多大佬的代码,怎么形容呢,就是各种各种设计模式,看起来真的无敌优雅,然后我们接入的时候还很方便,直接传参数就好了。
我们的业务代码中设计模式本身就是无处不在的,我在写这个文章的时候刻意翻看我们以前的项目,基本每个项目里面都能看到他们的身影,在跟我前同事聊过之后体会更深了。
其实我们想要走的更高更远,那我们学习的脚步就不能一直停下,后面我可能会针对设计模式写一个互联网公司的流程引擎,来看看我们针对更复杂的业务逻辑我们怎么运用框架去实现它。
我是 星河 ,你站的越高,你发现的也就越多,感谢各位人才的点赞、收藏和评论,我们下期见…