前言
带着问题阅读文章,为什么要用到设计模式,它实际带给你的收益有哪些,如何去使用…
为什么用创建型模式
- 创建型模式关注点 ’怎样创建出对象?‘
- “ 将对象的创建与使用分离”
- 降低系统的耦合度
- 使用者无需关注对象的创建细节
- 对象的创建由相关的工厂来完成(各种工厂模式)
- 对象的创建由一个建造者来完成(建造者模式)
- 对象的创建由原来对象克隆完成(原型模式)
- 对象始终在系统中只有一个实例(单例模式)
单例模式
简要说明
一个单一的类,负责创建自己的对象,同时确保系统中只有单个对象被创建。
单例特点
- 某个类只能有一个实例,(构造器私有)
- 它必须自行创建这个实例(自己编写实例化逻辑)
- 它必须自行向整个系统提供这个实例(对外提供实例化方法)
应用场景
- 多线程中的线程池
- 数据库的连接池
- 系统环境信息
- 上下文
面试问题
- 系统环境信息
- spring中怎么保持组件单例的?
- servletContext是什么?是单例吗?怎么保证?
- ApplicationContext是什么?是单例吗?怎么保证?
- 数据库连接池一般怎么创建出来的,怎么保证单例实例?
代码
/**
* 只能有一个
**/
public class Person {
private String name;
private String age;
// 懒汉、饿汉
private static Person instance;
//private static Person instance = new Person();// 饿汉
// 构造器私有,外部不能实例化
private Person() {
System.out.println("创建了 person ");
}
// 提供被外部的方法
// 1.public static synchronized Person guiguBoss() 锁太大
// 2.双重检查锁+内存可见性(设计模式)
// public static Person guiguBoss() {
// // 如果没有实例,再去创建
// // 这种方式就是懒汉
// if (instance == null) {
// synchronized (Person.class) {
// if (instance == null) {
// Person person = new Person();
// instance = person;
// }
// }
// }
//
// return instance;
// }
public static Person guiguBoss() {
// 如果没有实例,再去创建
// 这种方式就是懒汉
if (instance == null) {
synchronized (Person.class) {
if (instance == null) {
Person person = new Person();
instance = person;
}
}
}
return instance;
}
}
public class MainTest {
public static void main(String[] args) {
// Person person1 = Person.guiguBoss();
// Person person2 = Person.guiguBoss();
//
// System.out.println(person1 == person2);
// System.out.println(System.getProperties());
System.out.println(System.getenv());
}
}
原型模式
- 原型模式是用于创建重复的对象,同时又能保证性能。
应用场景
- 资源优化
- 性能和安全要求
- 一个对象多个修改者的场景
- 一个对象需要提供给其它对象访问,而且各个调用者可能都需要修改其值时可以考虑使用原型模式拷贝多个对象供调用者使用。
- 原型模式已经与Java融为一体,可以随手拿来用。
- …
代码
/**
* Cloneable:当前对象式可克隆的
**/
public class User implements Cloneable {
private String username;
private Integer age;
public User() {
System.out.println("user创建对象");
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
/**
* 再创建一个人,赋予我的属性
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
User user = new User();
user.setUsername(username);
user.setAge(age);
return user;
}
}
public class GuiguMybatis {
// 缓存user
private Map<String, User> userCache = new HashMap<>();
/**
* 从数据库查数据
* @return
*/
public User getUser(String username) throws CloneNotSupportedException {
User user = null;
// 缓存中没有
if (!userCache.containsKey(username)) {
// 查询数据库
user = getUserFromDb(username);
user = (User)user.clone();
} else {
// 从缓存中直接拿,缓存就会变脏
// 原型已经拿到,但是不能直接给(本人)
user = userCache.get(username);
// 从这个对象中快速得到一个克隆体(克隆人) == 原型模式
user = (User)user.clone();
}
return user;
}
private User getUserFromDb(String username) throws CloneNotSupportedException {
System.out.println("从数据库查用户"+username);
User user = new User();
user.setUsername(username);
user.setAge(18);
// 给缓存中放一个clone
userCache.put(username, (User)user.clone());
return user;
}
}
/**
* 原型
* 1. GuiguMybatis:操作数据库,从数据库里面查出很多记录
* 2. 每次查数据库,查到以后把所有数据都封装一个对象,返回。
* 100000 thread:查一个记录,每次创建一个对象封装并返回
* 系统里面就有100000个user,浪费内存
* 3. 解决:缓存,查过的保存
* 如果在查相同的记录,拿到原来的原型对象
*
* 4. 此时直接拿到缓存中的对象
**/
public class MainTest {
public static void main(String[] args) throws CloneNotSupportedException {
GuiguMybatis guiguMybatis = new GuiguMybatis();
// 得到克隆体
User user1 = guiguMybatis.getUser("zhangsan");
System.out.println("1 --> "+ user1);
user1.setUsername("ls");
System.out.println("zs自己改了 --> "+ user1);
// 得到克隆体
User user2 = guiguMybatis.getUser("zhangsan");
System.out.println("2 --> "+ user2);
User user3 = guiguMybatis.getUser("zhangsan");
System.out.println("3 --> "+ user3);
User user4 = guiguMybatis.getUser("zhangsan");
System.out.println("4 --> "+ user4);
System.out.println(user1 == user3);
}
}
总结
本体给外部提供一个克隆体进行使用
深克隆(两个完全不一样【递归克隆,内容却完全一样】)与浅克隆(只是属性赋值)…
工厂模式
工厂模式提供了一种创建对象的最佳方式。我们不关心对象的创建细节,只需要根据不同情况获取不同产品即可。
简单工厂
情景:汽车厂,生产汽车
三个角色:
- Factory:工厂角色,WuLinFactory
- Product:抽象产品角色,Car
- Concrete Product:具体产品角色,Van Car、MiniCar
缺点:违背开闭,扩展不易
代码
// 抽象工厂
public abstract class AbstractCar {
String engine;
public abstract void run();
}
// mini 汽车
public class MiniCar extends AbstractCar {
public MiniCar() {
this.engine = "四缸水平对置发动机";
}
@Override
public void run() {
System.out.println(engine + "---> 嘟嘟..");
}
}
// van 汽车
public class VanCar extends AbstractCar{
public VanCar() {
this.engine = "单杠柴油机";
}
@Override
public void run() {
System.out.println(engine + "----> 哒哒...");
}
}
/**
* 简单工厂
* 1. 产品数量极少
**/
public class WuLinSimpleFactory {
// 传class:好像具有扩展性,但没有实际解决问题
public AbstractCar newCar(String type) {
// 核心方法:一切从简
if ("van".equals(type)) {
return new VanCar();
} else if ("mini".equals(type)) {
return new MiniCar();
}
// 更多的产品,违反开闭原则。应该直接扩展出一个类来造
return null;
}
}
// 测试
public class MainTest {
public static void main(String[] args) {
WuLinSimpleFactory factory = new WuLinSimpleFactory();
AbstractCar van = factory.newCar("van");
AbstractCar mini = factory.newCar("mini");
AbstractCar ff = factory.newCar("f");
van.run();
mini.run();
}
}
工厂方法
四个角色
- Product: 抽象角色
- ConcreteProduct:具体chanp
- Factory:抽象工厂
- ConreteFactory:具体工厂
缺点:系统复杂度增加,产品单一
代码
/**
* 工厂的产品
*
* 怎么办把一个功能提升一个层次,定义抽象
* 抽象类,接口,就会有多实现,多实现自然多功能
**/
public abstract class AbstractCar {
String engine;
public abstract void run();
}
/**
* 抽象工厂的层次
**/
public abstract class AbstractCarFactory {
public abstract AbstractCar newCar();
}
public class MiniCar extends AbstractCar {
public MiniCar() {
this.engine = "四缸水平对置发动机";
}
@Override
public void run() {
System.out.println(engine + "---> 嘟嘟..");
}
}
public class RacingCar extends AbstractCar{
public RacingCar() {
this.engine = "v8发动机";
}
@Override
public void run() {
System.out.println(engine + "----> 嗖...");
}
}
public class VanCar extends AbstractCar {
public VanCar() {
this.engine = "单杠柴油机";
}
@Override
public void run() {
System.out.println(engine + "----> 哒哒...");
}
}
/**
* minicar 分厂
**/
public class WuLinMiniCarFactory extends AbstractCarFactory{
@Override
public AbstractCar newCar() {
return new MiniCar();
}
}
/**
* Racingcar 分厂
**/
public class WuLinRacingCarFactory extends AbstractCarFactory{
@Override
public AbstractCar newCar() {
return new RacingCar();
}
}
/**
* Van 分厂
**/
public class WuLinVanCarFactory extends AbstractCarFactory{
@Override
public AbstractCar newCar() {
return new VanCar();
}
}
// 测试
public class MainTest {
public static void main(String[] args) {
AbstractCarFactory carFactory = new WuLinRacingCarFactory();
AbstractCar abstractCar = carFactory.newCar();
abstractCar.run();
carFactory = new WuLinVanCarFactory();
AbstractCar abstractCar1 = carFactory.newCar();
abstractCar1.run();
}
}
总结:总厂 到分厂 分厂底下有生产wulin小车、wulin跑车
抽象工厂
情景:汽车厂除了生产汽车之外,还生产其它产品…
- 工厂模式的退化
- 当抽象工厂模式中每个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。
代码
情景:汽车厂不只生产汽车,还产口罩之类的
/**
* 工厂的产品
**/
public abstract class AbstractCar {
String engine;
public abstract void run();
}
public class RacingCar extends AbstractCar {
public RacingCar() {
this.engine = "v8发动机";
}
@Override
public void run() {
System.out.println(engine + "----> 嗖...");
}
}
public class VanCar extends AbstractCar {
public VanCar() {
this.engine = "单杠柴油机";
}
@Override
public void run() {
System.out.println(engine + "----> 哒哒...");
}
}
/**
* 抽象产品:口罩
**/
public abstract class AbstractMask {
Integer price;
public abstract void protectedMe();
}
// 普通口罩
public class CommonMask extends AbstractMask{
public CommonMask() {
this.price = 1;
}
@Override
public void protectedMe() {
System.out.println("普通口罩..简单保护...及时更换");
}
}
// n95 口罩
public class N95Mask extends AbstractMask{
public N95Mask() {
this.price = 2;
}
@Override
public void protectedMe() {
System.out.println("n95口罩...超级防护");
}
}
// 总厂
public abstract class WuLinFactory {
List<String> rules;// 规范
abstract AbstractCar newCar();// 生产车
abstract AbstractMask newMask();// 生产口罩
}
/**
* 总厂下的汽车公司
* wulin 汽车集团
**/
public abstract class WuLinCarFactory extends WuLinFactory{
abstract AbstractCar newCar();
@Override
AbstractMask newMask() {
return null;
}
}
/**
* 具体工厂:只造车
**/
public class WuLinRacingFactory extends WuLinCarFactory{
@Override
AbstractCar newCar() {
return new RacingCar();
}
}
public class WuLinVanCarFactory extends WuLinCarFactory{
@Override
AbstractCar newCar() {
return new VanCar();
}
}
/**
* wulin 口罩集团
**/
public abstract class WuLinMaskFactory extends WuLinFactory{
@Override
AbstractCar newCar() {
return null;
}
abstract AbstractMask newMask();
}
// 杭州分厂:口罩
public class WuLinHangZhouMaskFactory extends WuLinMaskFactory{
@Override
AbstractMask newMask() {
return new CommonMask();
}
}
// 武汉分厂:口罩
public class WuLinWuHanMaskFactory extends WuLinMaskFactory{
@Override
AbstractMask newMask() {
return new N95Mask();
}
}
/**
* 抽象出来:
* 可以抽象成接口(只有方法)
* 或抽象类(有些属性也需要使用)
**/
public class MainTest {
public static void main(String[] args) {
WuLinFactory wuLinFactory = new WuLinWuHanMaskFactory();
AbstractMask abstractMask = wuLinFactory.newMask();
abstractMask.protectedMe();
wuLinFactory = new WuLinHangZhouMaskFactory();
AbstractMask abstractMask1 = wuLinFactory.newMask();
abstractMask1.protectedMe();
}
}
应用场景
- NumberFormat、SimpleDateFormat
- LoggerFactory
- SqlSessionFactory
- BeanFactory
- …
建造者模式
三个角色
- 产品角色(Product):Phone
- 抽象构造者(Builder):AbstractPhoneBuilder
- 具体构建者(Concrete Builder):PhoneBuilder
代码
public abstract class AbstractBuilder {
Phone phone;
abstract AbstractBuilder customCpu(String cpu);
abstract AbstractBuilder customMem(String mem);
abstract AbstractBuilder customDisk(String disk);
abstract AbstractBuilder customCam(String cam);
Phone getProduct() {
return phone;
}
}
public class Phone {
protected String cpu;// 手机cpu
protected String mem;// 内存
protected String disk;// 磁盘
protected String cam;// 像素
@Override
public String toString() {
return "Phone{" +
"cpu='" + cpu + '\'' +
", mem='" + mem + '\'' +
", disk='" + disk + '\'' +
", cam='" + cam + '\'' +
'}';
}
public String getCpu() {
return cpu;
}
public String getMem() {
return mem;
}
public String getDisk() {
return disk;
}
public String getCam() {
return cam;
}
}
public class XiaoMiBuilder extends AbstractBuilder{
public XiaoMiBuilder() {
//phone = new Phone();
phone = Phone.builder().build();
}
@Override
AbstractBuilder customCpu(String cpu) {
phone.cpu = cpu;
return this;
}
@Override
AbstractBuilder customMem(String mem) {
phone.mem = mem;
return this;
}
@Override
AbstractBuilder customDisk(String disk) {
phone.disk = disk;
return this;
}
@Override
AbstractBuilder customCam(String cam) {
phone.cam = cam;
return this;
}
}
public class MainTest {
public static void main(String[] args) {
// XiaoMiBuilder builder = new XiaoMiBuilder();
// 建造这个手机
// builder.customMem("16G");
// builder.customDisk("1T");
// builder.customCam("2亿");
// builder.customCpu("晓龙8888");
// Phone phone = builder.getProduct();
// System.out.println(phone);
// 链式建造者: swagger
// Phone phone1 = builder.customCpu("晓龙8888")
// .customCam("2亿")
// .customDisk("1T")
// .customMem("16G")
// .getProduct();
//
//
// System.out.println(phone1);
Phone.PhoneBuilder builder1 = Phone.builder();
Phone build = builder1.cpu("1").mem("2").cam("3").disk("4").build();
System.out.println(build);
}
}
手机由cpu、磁盘、内存等一系列参数组成,而不同手机不同参数
应用场景
- StringBuilder
- Swagger-ApiBuilder
- 快速实现 。Lombok-Builder模式