🌐 设计模式及源码分析(二)

三、创建型模式的作用

3.2原型(Prototype)模式

每一个高可用的框架都是设计模式嵌套使用,而不是单个使用

本体给外部提供一个克隆进行使用,这时候本体就是原型 ,这种方式可以避免重复创建相同的对象,提高了性能和效率。

就比如从数据库查询数据,每次查询的数据都一样,这时候就多次查询的数据就很占用空间,我们一般可以用Redis进行缓存如果查询条件一样就从缓存读取。

原型模式的代码实现

1.建立 Dog 类提供了clone()方法

java 复制代码
/**
 * 当前对象是可克隆的
 */
public class Dog implements Cloneable {

    private String dogName;
    private Integer age;

    public Dog() {
        System.out.println("创建了Dog对象");
    }

    public String getDogName() {
        return dogName;
    }

    public void setDogName(String dogName) {
        this.dogName = dogName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "dogName='" + dogName + ''' +
                ", age=" + age +
                '}';
    }


   //再创建一只狗,赋予所有属性
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Dog dog = new Dog();
        dog.setDogName(dogName);
        dog.setAge(age);
        return dog;
    }
}

2.建立DogData 类:(模拟从数据库拿数据)

java 复制代码
public class DogData {

    //缓存user.序列化和反序列化-深克隆
    private Map<String, Dog> dogCache = new HashMap<>();

    /**
     * 从数据库查数据
     * @return
     */
    public Dog getUser(String username) throws Exception {
        Dog dog = null;
        //缓存中没有
        if(!dogCache.containsKey(username)){
            //查询数据库
            dog = getUserFromDb(username);
        }else {
            //从缓存中直接拿,脏缓存问题
            //原型已经拿到,但是不能直接给。(
            dog = dogCache.get(username);
            System.out.println("从缓存中拿到的是:"+ dog);
            //从这个对象快速得到一个克隆体 == 原型模式
            dog = (Dog) dog.clone();
        }

        return dog;
    }

    private Dog getUserFromDb(String username) throws Exception{
        System.out.println("从数据库查到:"+username);
        Dog dog = new Dog();
        dog.setDogName(username);
        dog.setAge(18);
        //给缓存中放一个clone
        dogCache.put(username, (Dog) dog.clone());
        return dog;
    }


}

3.建立DogTest

Java 复制代码
public class DogTest {

    public static void main(String[] args) throws Exception {
        DogData dogData = new DogData();

        //得到的是克隆体
        Dog 泰迪 = dogData.getUser("泰迪");
        System.out.println("1==>"+泰迪);
        泰迪.setDogName("泰迪副本");
        System.out.println("泰迪自己改了:"+泰迪);


        //得到的是克隆体
        Dog 金毛 = dogData.getUser("泰迪");
        System.out.println("2-->"+金毛);

        //得到的是克隆体
        Dog 柯基 = dogData.getUser("泰迪");
        System.out.println("3-->"+柯基);

        //得到的是克隆体
        Dog 柴犬 = dogData.getUser("泰迪");
        System.out.println("4-->"+柴犬);
        System.out.println(泰迪 == 柯基);

    }
}

以上代码就实现了原型模式

泰迪创建了克隆体并放入缓存当中,如果金毛等需要泰迪的数据就从缓存中拿,即使泰迪更改了名字,也不会影响,因为克隆体已存在在缓存当中,不再改变

3.3工厂(Factory)模式

工厂模式是一种用于管理对象创建的设计模式,可以提高代码的可扩展性和可维护性

1.简单工厂(Simple Factory )

简单工厂中有三个角色

  • Factory:工厂角色, ChinaSimpleFactory
  • Product:抽象产品角色,AbstractPhone
  • ConcreteProduct:具体产品角色, HuaWeiPhoneXiaoMiPhone

1.建立 AbstractPhone(抽象类,定义了一个品牌变量和一个抽象方法)

java 复制代码
public abstract class AbstractPhone {

    String brand;
    public abstract void make();
}

2.建立HuaWeiPhone 类:(继承抽象类,并实现其中的方法,生产华为手机)

Java 复制代码
public class HuaWeiPhone extends AbstractPhone {
    public HuaWeiPhone(){
        this.brand = "华为手机";
    }

    @Override
    public void make() {
        System.out.println(brand +"--》数智世界 一触即达");
    }
}

3.建立XiaoMiPhone 类:(继承抽象类,并实现其中的方法,生产小米手机)

Java 复制代码
public class XiaoMiPhone extends AbstractPhone {

    public XiaoMiPhone(){
        this.brand = "小米手机";
    }

    @Override
    public void make() {
        System.out.println(brand +"--> 遥遥领先");
    }
}

4.建立ChinaSimpleFactory 类:(一个简单的工厂,用来管理各个产品)

Java 复制代码
public class ChinaSimpleFactory {

    /**
     *
     * @param type  Class: 好像具有扩展性,但是没有解决实际问题
     * @return
     */
    public AbstractPhone newCar(String type){

        //核心方法:一切从简
        if("HuaWei".equals(type)){
            // 钣金、喷漆、放发动机、申请环保

            return new HuaWeiPhone();
        }else if("XiaoMi".equals(type)){
            return new XiaoMiPhone();
        }

        //.....

        return null;
    }
}

5.建立MainTest测试

java 复制代码
public class MainTest {

    public static void main(String[] args) {

        ChinaSimpleFactory factory = new ChinaSimpleFactory();

        AbstractPhone huaWei = factory.newCar("HuaWei");
        AbstractPhone xiaoMi = factory.newCar("XiaoMi");
        huaWei.make();
        xiaoMi.make();

    }
}

简单工厂的缺点

如果有更多的品牌手机,在工厂中就需要添加更多的if else 代码,违反开闭原则。应该直接扩展出一个类来造

2.工厂方法(Factory Method)

工厂方法有四个角色

  • Product:抽象产品 AbstractPhone
  • ConcreteProduct:具体产品 HuaWeiPhone、XiaoMiPhone
  • Factory:抽象工厂 AbstractPhoneFactory
  • ConcreteFactory:具体工厂 HuaWeiPhoneFactory、XiaoMiPhoneFactory

1.建立AbstractPhone(抽象类,定义了一个品牌变量和一个抽象方法)

Java 复制代码
public abstract class AbstractPhone {

    String brand;
    public abstract void make();
}

2.建立HuaWeiPhone、XiaoMiPhone(继承抽象类,并实现其中的方法,生产华为、小米手机)

Java 复制代码
public class HuaWeiPhone extends AbstractPhone {
    public HuaWeiPhone(){
        this.brand = "华为手机";
    }

    @Override
    public void make() {
        System.out.println(brand +"数智世界 一触即达");
    }
}


public class XiaoMiPhone extends AbstractPhone {

    public XiaoMiPhone(){
        this.brand = "小米手机";
    }

    @Override
    public void make() {
        System.out.println(brand +"--> 遥遥领先...");
    }
}

3.建立AbstractPhoneFactory (一个手机的抽象类)

csharp 复制代码
public abstract class AbstractPhoneFactory {

    public abstract AbstractPhone newPhone();
    //我能造口罩.....
}

4.建立HuaWeiPhoneFactory、XiaoMiPhoneFactory (华为、小米的工厂类)

Java 复制代码
public class HuaWeiPhoneFactory extends AbstractPhoneFactory {
    @Override
    public AbstractPhone newPhone() {
        return new HuaWeiPhone();
    }
}

public class XiaoMiPhoneFactory extends AbstractPhoneFactory {
    @Override
    public AbstractPhone newPhone() {
        return new XiaoMiPhone();
    }
}

5.建立测试类MainTest

java 复制代码
public class MainTest {

    public static void main(String[] args) {

        AbstractPhoneFactory phoneFactory = new XiaoMiPhoneFactory();
        AbstractPhone abstractXiaoMiPhone = phoneFactory.newPhone();
        abstractXiaoMiPhone.make();
        
        phoneFactory = new HuaWeiPhoneFactory();
        AbstractPhone abstractHuaWeiPhone = phoneFactory.newPhone();
        abstractHuaWeiPhone.make();
    }
}

工厂方法实现了面向接口编程,当然缺点就是:当系统复杂度增加时,工厂方法的品类过于单一,就比如华为和小米不仅要造手机,当要造汽车的时候就很难去优化了

3.抽象工厂(Abstract Factory)

提供了一个接口来创建一系列相关或相互依赖的对象,而无需指定它们具体的类。

它将具体产品的创建与使用分离,使得系统更加灵活和可扩展。当需要添加新的产品类型时,只需要实现新的具体工厂类,而不需要修改使用这些产品的其他部分。

1.建立AbstractCarAbstractPhone 抽象类 (定义了汽车名字,汽车制造方法,手机名字,手机自造方法)

Java 复制代码
public abstract class AbstractCar {

    String carName;
    public abstract void run();
}


public abstract class AbstractPhone {

    String brand;
    public abstract void make();
}

2.建立HuaWeiCar、HuaWeiPhone、XiaoMiCar、XiaoMiPhone (实现制造手机和汽车)

Java 复制代码
public class HuaWeiCar extends AbstractCar {
    public HuaWeiCar(){
        this.carName = "华为汽车";
    }

    @Override
    public void run() {
        System.out.println(carName +"数智世界 一触即达");
    }
}

public class HuaWeiPhone extends AbstractPhone {
    public HuaWeiPhone(){
        brand = "华为";
    }
    @Override
    public void make() {
        System.out.println("数智世界 一触即达");
    }
}

public class XiaoMiCar extends AbstractCar {

    public XiaoMiCar(){
        this.carName = "小米汽车";
    }
    @Override
    public void run() {
        System.out.println(carName +"遥遥领先");
    }
}

public class XiaoMiPhone extends AbstractPhone {

    public XiaoMiPhone(){
        this.brand = "小米";
    }

    @Override
    public void make() {
        System.out.println("瑶瑶领先");
    }
}

3.建立 ChinaFactory (定义了汽车、手机制造两个抽象方法)

java 复制代码
public abstract class ChinaFactory {

    abstract AbstractCar newCar();
    abstract AbstractPhone newPhone();
}

4.建立ChinaPhoneFactory 、ChinaCarFactory (定义了汽车、手机制造中的一个方法)

Java 复制代码
public  abstract  class ChinaCarFactory extends ChinaFactory {
    @Override
    abstract  AbstractCar newCar();

    @Override
    AbstractPhone newPhone() {
        return null;
    }
}


public abstract class ChinaPhoneFactory extends ChinaFactory {
    @Override
    AbstractCar newCar() {
        return null;
    }

    abstract AbstractPhone newPhone();
}

5.建立ChinaHuaWeiCarFactory、ChinaHuaWeiPhoneFactory、ChinaXiaoMiCarFactory、ChinaXiaoMiPhoneFactory (实现各种品牌的手机、汽车制造工厂)

Java 复制代码
public class ChinaHuaWeiCarFactory extends ChinaCarFactory {
    @Override
    AbstractCar newCar() {
        return new HuaWeiCar();
    }

}

public class ChinaHuaWeiPhoneFactory extends ChinaPhoneFactory {

    @Override
    AbstractPhone newPhone() {
        return new HuaWeiPhone();
    }
}

public class ChinaXiaoMiCarFactory extends ChinaCarFactory {
    @Override
    AbstractCar newCar() {
        return new XiaoMiCar();
    }
}

public class ChinaXiaoMiPhoneFactory extends ChinaPhoneFactory {

    @Override
    AbstractPhone newPhone() {
        return new XiaoMiPhone();
    }
}

6.建立测试类MainTest

Java 复制代码
public class MainTest {

    public static void main(String[] args) {

        //

        ChinaFactory chinaFactory = new ChinaXiaoMiPhoneFactory();
        AbstractPhone xiaoMiPhone = chinaFactory.newPhone();
        xiaoMiPhone.make();

        chinaFactory =new ChinaXiaoMiCarFactory();
        AbstractCar xiaoMiCar = chinaFactory.newCar();
        xiaoMiCar.run();


        chinaFactory = new ChinaHuaWeiPhoneFactory();
        AbstractPhone huaWeiPhone = chinaFactory.newPhone();
        huaWeiPhone.make();

        chinaFactory = new ChinaHuaWeiCarFactory();
        AbstractCar huaWeiCar = chinaFactory.newCar();
        huaWeiCar.run();
    }
}

以上代码就实现了抽象工厂,虽然刚开始需要建立很多的抽象类,还有抽象工厂,但是后面扩展很方便,系统需要增强新的功能只需要建立相应的抽象、抽象工厂、实现类即可

3.4 建造者(Builder)模式

建造者模式中三个角色

  • 产品角色(Product):Phone
  • 抽象建造者(Builder):AbstractBuilder
  • 具体建造者(Concrete Builder):XiaomiBuilder

1.建立 Phone(定义了一个手机类包含了各种参数)

java 复制代码
@Builder
@ToString
public class Phone {

    protected String cpu;
    protected String mem;
    protected String disk;
    protected String cam;
    
}

2.建立 AbstractBuilder 抽象类 (定义了制造手机参数方法的抽象类)

Java 复制代码
public abstract class AbstractBuilder  {

    Phone phone;
    abstract AbstractBuilder makeCpu(String cpu);
    abstract AbstractBuilder makeMem(String mem);
    abstract AbstractBuilder makeDisk(String disk);
    abstract AbstractBuilder makeCam(String cam);

    Phone getProduct(){
        return phone;
    }
}

3.建立XiaomiBuilder(实现了抽象类中的方法)

typescript 复制代码
public class XiaomiBuilder  extends AbstractBuilder{


    public XiaomiBuilder(){
        phone = Phone.builder().build();
    }

   
    @Override
    AbstractBuilder makeCpu(String cpu) {
        phone.cpu = cpu;
        return this;
    }

    @Override
    AbstractBuilder makeMem(String mem) {
        phone.mem = mem;
        return this;
    }

    @Override
    AbstractBuilder makeDisk(String disk) {
        phone.disk = disk;
        return this;
    }

    @Override
    AbstractBuilder makeCam(String cam) {
        phone.cam = cam;
        return this;
    }
}

4.建立测试类MainTest

java 复制代码
public class MainTest {

    public static void main(String[] args) {

        AbstractBuilder builder = new XiaomiBuilder();
        //链式建造者
        Phone phone = builder.makeCpu("骁龙8个8")
                .makeCam("2亿")
                .makeDisk("1T")
                .makeMem("16G")
                .getProduct();
        System.out.println(phone);

        //lombok提供的建造模式
        Phone build = Phone.builder()
                .cpu("1亿")
                .mem("2T")
                .cam("3G")
                .build();
        System.out.println(build);


    }
}
相关推荐
llz_1122 小时前
web-第二次课后作业
前端·后端·web
红尘散仙8 小时前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
卷毛的技术笔记9 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
会编程的土豆9 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
喵个咪10 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
basketball61610 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
qq_25183645710 小时前
SpringBoot+Vue 共享电池柜管理系统 完整实现 前后端分离项目实战 完整代码
vue.js·spring boot·后端
zhangxingchao11 小时前
AI 大模型核心六:量化、Workflow 与 Agent、多轮 RAG
前端·人工智能·后端
IT_陈寒12 小时前
Vite打包时遇到的坑,原来问题出在这里
前端·人工智能·后端
ayqy贾杰13 小时前
基层管理的三板斧,在AI时代行不通了
前端·后端·团队管理