设计模式(学习笔记)(第二章,创建型模式)
创建型模式
关注点:怎样创建出对象
将对象的创建和使用分离,降低系统的耦合性
使用者无需关注对象的创建细节
- 对象的创建由相关的工厂来完成;(各种工厂模式)
- 对象的创建由一个建造者来完成;(建造者模式)
- 对象的创建由原来对象克隆完成;(原型模式)
- 对象始终在系统中只有一个实例;(单例模式)
1. 单例
一个单一的类,负责创建自己的对象,同时确保系统中只有单个对象被创建。
单例特点:
- 某个类只有一个实例(构造器私有)
- 它必须自行创建这个实例(自己编写实例化逻辑)
- 它必须自行向整个系统提供这个实例;(对外提供实例化方法)
packagesjms.Creational.Singleton;/** * 单例对象 */publicclassSingleObject{/** * 自行创建这个对象 * 根据这个对象创建的时机分为饿汉和懒汉 * 饿汉:一开始就创建,例如:静态变量创建 * 懒汉:我用到这个对象才创建,在getInstance方法中创建 */privatevolatilestaticSingleObjectinstance;/** * 构造器私有 */privateSingleObject(){}/** * 向整个系统提供这个实例 * @return *///懒汉第二种,if+synchronized方法锁创建,锁太重,性能有影响// public synchronized static SingleObject getInstance(){publicstaticSingleObjectgetInstance(){//懒汉第一种if创建,会有多线程问题。/*if(instance==null){ instance = new SingleObject(); }*///懒汉第三种 双重检查锁+volatile关键字(防止指令重排)if(instance==null){synchronized(SingleObject.class){if(instance==null){instance=newSingleObject();}}}returninstance;}publicstaticvoidmain(String[]args){SingleObjectinstance=SingleObject.getInstance();SingleObjectinstance2=SingleObject.getInstance();System.out.println(instance);System.out.println(instance2);}}2. 原型
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。
本体给外部提供一个克隆体进行使用。
深拷贝,浅拷贝
packagesjms.Creational.Prototype;importlombok.Data;@DatapublicclassUserimplementsCloneable{privateStringname;privateIntegerage;/** * 克隆对象的方法。 * @return * @throws CloneNotSupportedException */@OverrideprotectedObjectclone()throwsCloneNotSupportedException{Useruser=newUser();user.setName(name);user.setAge(age);returnuser;}}packagesjms.Creational.Prototype;importjava.util.HashMap;importjava.util.Map;publicclassGuiguMybatis{//缓存user.序列化和反序列化-深克隆privateMap<String,User>userCache=newHashMap<>();/** * 从数据库查数据 * @return */publicUsergetUser(Stringusername)throwsException{Useruser=null;//缓存中没有if(!userCache.containsKey(username)){//查询数据库user=getUserFromDb(username);}else{//从缓存中直接拿,脏缓存问题//原型已经拿到,但是不能直接给。(本人)user=userCache.get(username);System.out.println("从缓存中拿到的是:"+user);//从这个对象快速得到一个克隆体(克隆人)==原型模式user=(User)user.clone();}returnuser;}privateUsergetUserFromDb(Stringname)throwsException{System.out.println("从数据库查到:"+name);Useruser=newUser();user.setName(name);user.setAge(18);//给缓存中放一个cloneuserCache.put(name,(User)user.clone());returnuser;}publicstaticvoidmain(String[]args)throwsException{GuiguMybatismybatis=newGuiguMybatis();//十分危险//得到的是克隆体Userzhangsan1=mybatis.getUser("zhangsan");System.out.println("1==>"+zhangsan1);zhangsan1.setName("李四2.。。");System.out.println("zhangsan1自己改了:"+zhangsan1);//得到的是克隆体Userzhangsan2=mybatis.getUser("zhangsan");System.out.println("2-->"+zhangsan2);//得到的是克隆体Userzhangsan3=mybatis.getUser("zhangsan");System.out.println("3-->"+zhangsan3);//得到的是克隆体Userzhangsan4=mybatis.getUser("zhangsan");System.out.println("4-->"+zhangsan4);System.out.println(zhangsan1==zhangsan3);}}3.工厂模式
工厂模式(Factory Pattern)提供了一种创建对象的最佳方式。我们不必关心对象的创建细节,只需要根据不同情况获取不同产品即可。难点:写好我们的工厂。
3.1 简单 工厂
三个角色
Factory:工厂角色, WuLinFactory
Product:抽象产品角色,Car
ConcreteProduct:具体产品角色, VanCar、MiniCar
//抽象产品角色publicabstractclassCar{publicStringengine;publicvoidrun(){System.out.println(engine+"开始运行了");}}//具体产品角色publicclassMiniCarextendsCar{publicMiniCar(){this.engine="mini发动机";}}//具体产品角色publicclassVanCarextendsCar{publicVanCar(){this.engine="v8发动机";}}//工厂角色publicclassWuLinFactory{publicCarnewCar(Stringtype){if("van".equals(type)){returnnewVanCar();}elseif("mini".equals(type)){returnnewMiniCar();}returnnull;}publicstaticvoidmain(String[]args){WuLinFactorywuLinFactory=newWuLinFactory();Carvan=wuLinFactory.newCar("van");van.run();Carmini=wuLinFactory.newCar("mini");mini.run();}}缺点:违背开闭,扩展不易
3.2 工厂方法 (多态工厂)
怎么把一个功能提升一个层次:定义抽象(抽象类,接口),抽象类,接口 就会有多实现,多实现自然就有多功能
四个角色
Product:抽象产品
ConcreteProduct:具体产品
Factory:抽象工厂
ConcreteFactory:具体工厂
//抽象产品publicabstractclassCar{publicStringengine;publicvoidrun(){System.out.println(engine+"开始运行了");}}//具体产品publicclassMiniCarextendsCar{publicMiniCar(){this.engine="mini发动机";}}//具体产品publicclassVanCarextendsCar{publicVanCar(){this.engine="v8发动机";}}//抽象工厂publicabstractclassWuLinFactory{publicabstractCarnewCar();}//具体工厂publicclassWuLinMiniFactoryextendsWuLinFactory{@OverridepublicCarnewCar(){returnnewMiniCar();}}//具体工厂publicclassWuLinVanFactoryextendsWuLinFactory{@OverridepublicCarnewCar(){returnnewVanCar();}}//测试publicclassMainTest{publicstaticvoidmain(String[]args){WuLinFactoryfactory=newWuLinMiniFactory();Carcar=factory.newCar();car.run();WuLinFactoryfactory2=newWuLinVanFactory();Carcar2=factory2.newCar();car2.run();}}缺点:系统复杂度增加,产品单一
4.抽象工厂
产品等级结构:产品等级结构即产品的 继承结构,如一个抽象类是手机 ,其子类有小米手机、华为手机
产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。
当抽象工厂模式中每一个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。
//抽象产品publicabstractclassCar{publicStringengine;publicvoidrun(){System.out.println(engine+"开始运行了");}}//具体产品publicclassMiniCarextendsCar{publicMiniCar(){this.engine="mini发动机";}}//具体产品publicclassVanCarextendsCar{publicVanCar(){this.engine="v8发动机";}}publicabstractclassMask{publicIntegerprice;publicStringname;publicvoidprotectMe(){System.out.println(name+"的口罩,价格是:"+price);}}publicclassCommonMaskextendsMask{publicCommonMask(){this.price=1;this.name="普通口罩";}}publicclassN95MaskextendsMask{publicN95Mask(){this.price=20;this.name="N95口罩";}}//抽象工厂publicabstractclassWuLinFactory{publicabstractCarnewCar();publicabstractMasknewMask();}//具体工厂publicclassWuLinMiniFactoryextendsWuLinFactory{@OverridepublicCarnewCar(){returnnewMiniCar();}@OverridepublicMasknewMask(){returnnull;}}//具体工厂publicclassWuLinVanFactoryextendsWuLinFactory{@OverridepublicCarnewCar(){returnnewVanCar();}@OverridepublicMasknewMask(){returnnull;}}publicclassWuLinCommonMaskFactoryextendsWuLinFactory{@OverridepublicCarnewCar(){returnnull;}@OverridepublicMasknewMask(){returnnewCommonMask();}}publicclassWuLinN95MaskFactoryextendsWuLinFactory{@OverridepublicCarnewCar(){returnnull;}@OverridepublicMasknewMask(){returnnewN95Mask();}}publicclassMainTest{publicstaticvoidmain(String[]args){WuLinFactoryfactory1=newWuLinVanFactory();Carcar1=factory1.newCar();car1.run();WuLinFactoryfactory2=newWuLinMiniFactory();Carcar2=factory2.newCar();car2.run();WuLinFactoryfactory3=newWuLinN95MaskFactory();Maskmask1=factory3.newMask();mask1.protectMe();WuLinFactoryfactory4=newWuLinCommonMaskFactory();Maskmask2=factory4.newMask();mask2.protectMe();}}5.建造者
产品角色(Product):Phone
抽象建造者(Builder):AbstracPhoneBuilder
具体建造者(Concrete Builder):PhoneBuilder
创建的东西细节复杂,还必须暴露给使用者。屏蔽过程而不屏蔽细节
将复杂对象的构建过程分离出来,使得同样的构建过程可以创建不同的表示
//产品角色publicclassPhone{protectedStringcpu;protectedStringmem;protectedStringdisk;protectedStringcam;@OverridepublicStringtoString(){return"Phone{"+"cpu='"+cpu+'\''+", mem='"+mem+'\''+", disk='"+disk+'\''+", cam='"+cam+'\''+'}';}publicStringgetCpu(){returncpu;}publicStringgetMem(){returnmem;}publicStringgetDisk(){returndisk;}publicStringgetCam(){returncam;}}//抽象建造者publicabstractclassAbstractBuilder{Phonephone;abstractAbstractBuildercustomCpu(Stringcpu);abstractAbstractBuildercustomMem(Stringmem);abstractAbstractBuildercustomDisk(Stringdisk);abstractAbstractBuildercustomCam(Stringcam);PhonegetProduct(){returnphone;}}//具体建造者publicclassXiaomiBuilderextendsAbstractBuilder{publicXiaomiBuilder(){phone=newPhone();}/** * @param cpu */@OverrideAbstractBuildercustomCpu(Stringcpu){phone.cpu=cpu;returnthis;}@OverrideAbstractBuildercustomMem(Stringmem){phone.mem=mem;returnthis;}@OverrideAbstractBuildercustomDisk(Stringdisk){phone.disk=disk;returnthis;}@OverrideAbstractBuildercustomCam(Stringcam){phone.cam=cam;returnthis;}}lambok提供的简单方法
Phone类上加上@BuilderPhonebuild=Phone.builder().cpu("1").mem("2").cam("3").disk("4").build();