专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java中的23种设计模式之工厂模式(java23种设计模式)

temp10 2024-10-23 15:12:31 java教程 17 ℃ 0 评论

工厂模式分为简单工厂模式工厂方法模式抽象工厂模式三种。

工厂模式的特点:用户不用关心对象如何创建,只需要消费对象即可。

Java中的23种设计模式之工厂模式(java23种设计模式)

工厂模式都属于创建型模式

创建型模式:抽象了类的实例化,将类的创建和使用解耦,外界只需要知道统一的调用接口,不需要关心具体创建过程。

简单工厂模式

又叫静态工厂模式,不属于23种设计模式,是工厂模式的一种特殊实现。

通过传递参数,动态决定创建哪一种类型实例。

包括三种角色。

工厂角色:简单工厂模式的核心,创建具体产品角色的核心逻辑。外界可以直接调用工厂类,创建需要的对象,一般是通过传递不同的参数,确定不同的对象。

抽象产品角色:具体产品实例的父类(接口)

具体产品角色:工厂模式最终创建的具体产品实例

示例

我们以《斗罗大陆》里面魂师获取魂环为例。

魂师修炼到一定等级之后,需要通过魂环获得魂技,魂环由魂兽产生,魂兽生活在星斗大森林里,魂师通过在星斗大森林里猎杀魂兽获得魂环。

我们可以这样认为:

星斗大森林就相当于一个产生各种魂环的工厂,扮演工厂角色

魂环有十年、百年、千年、万年、十万年等,不同年限的魂环由不同的魂兽产生,那么魂兽就相当于产生魂环的抽象产品,而魂环则是具体的产品

魂师进入星斗大森林工厂,根据自己需要获取不同年限的魂环。

代码示例

魂师有两个属性姓名和武魂。(代码太多占空间,只显示核心代码

/**
 * 魂师
 */
public class SoulMaster {
    String name;//姓名
    String soulWu;//武魂
}

抽象产品,魂兽产生魂环接口

/**
 * 魂兽产生魂环接口
 */
public interface  SoulBest {
    //魂兽可以产生魂环
    String produceSouleRing();
}

具体产品,魂环:十年、百年、千年、万年、十万年,凶兽魂环,百万年魂环

public class SoulRing10 implements SoulBest{
    @Override
    public String produceSouleRing() {
        return "十年魂环";
    }
}
public class SoulRing100 implements SoulBest{
    @Override
    public String produceSouleRing() {
        return "百年魂环";
    }
}
public class SoulRing1w implements SoulBest{
    @Override
    public String produceSouleRing() {
        return "万年魂环";
    }
}
//此处省略很多魂环代码

星斗大森林,产生魂环的工厂

//星斗大森林相当于产生魂环的工厂
public class StarsForestFactory {
    public static SoulBest getSoulRing(int year) {
        //猎杀不同年限魂兽,获得不同的魂环
        SoulBest soulBest = null;
        if (year >= 0 && year <= 100) {
            soulBest = new SoulRing10();//十年魂环
        } else if (year > 100 && year < 1000) {
            soulBest = new SoulRing100();//百年魂环
        } else if (year >=1000 && year < 10000) {
            soulBest = new SoulRing1k();//千年魂环
        }else if (year >=10000 && year < 100000) {
            soulBest = new SoulRing1w();//万年魂环
        }else if (year >=100000 && year < 200000) {
            soulBest = new SoulRing10w();//十万年魂环
        }else if (year >=200000 && year < 1000000) {
            soulBest = new SoulRing10wplus();//凶兽魂环
        }else if (year >=1000000) {
            soulBest = new SoulRing100w();//百万年魂环
        }
        return soulBest;
    }
}

给我们的魂师们获取魂环

public class GetSoulRing {
    public static void main(String[] args) {
        //创建魂师
        ArrayList<SoulMaster> sms = new ArrayList<>();
        sms.add(new SoulMaster("唐三","昊天锤"));
        sms.add(new SoulMaster("霍雨浩","灵眸"));
        sms.add(new SoulMaster("唐舞麟","蓝银皇"));
        sms.add(new SoulMaster("蓝轩宇","银纹蓝银皇"));
        SoulBest  soulBest;
        int soulRingYear = 0;
        for(SoulMaster sm : sms){
            soulRingYear=random();//随即生成需要获取的魂环年限
            soulBest = StarsForestFactory.getSoulRing(soulRingYear);
            System.out.println(sm.getName()+"为武魂【"+sm.getSoulWu()
                               +"】获取了【"+soulBest.produceSouleRing()+"】");
        }
    }
}

运行结果

唐三为武魂【昊天锤】获取了【千年魂环】

霍雨浩为武魂【灵眸】获取了【十年魂环】

唐舞麟为武魂【蓝银皇】获取了【十年魂环】

蓝轩宇为武魂【银纹蓝银皇】获取了【千年魂环】

简单工厂的缺点是:所有的逻辑都写在工厂类,如果产品多,会很臃肿,添加新产品需要修改工厂类。

适用创建对象不多的场景。

工厂方法模式

简单工厂模式里面,工厂方法是静态属性,不能被继承重写。

工厂方法模式,提供一个抽象工厂角色,由抽象工厂的子类进行具体的逻辑处理。将对象的创建推迟到子类中。避免了简单工程模式中,工厂类可能会出现的臃肿问题。

包括四种角色。

抽象工厂角色:工厂方法模式的核心,同应用程序无关,具体工厂必须继承或实现抽象工厂。

具体工厂角色:包括具体的业务逻辑代码,由具体的产品调用创建。

抽象产品角色:具体产品的父类。

具体产品角色:最终创建的产品实例。

示例

随着魂师不断猎杀魂兽,魂兽濒临灭绝,于是魂师和魂兽之间爆发了战争,而在大战之际,一个划时代意义组织——传灵塔诞生了。

传灵塔创建了魂灵体系,魂灵分为白色、黄色、紫色、黑色、红色、橙色和金色,分别提供十年、百年、千年等不同年限的魂环。

魂灵的出现让魂师不再依靠猎杀魂兽来获取魂环。

我们可以这样认为:

传灵塔相当于一个魂灵制造工厂,工厂下面不同的生产线制造不同类型的魂灵。

传灵塔是抽象工厂,它可以制造任何魂灵。

生产线相当于抽象工厂的子类,负责生产魂师需要的魂灵,是具体的工厂。

魂灵是是提供魂环的抽象产品。

魂环则是魂灵提供的具体产品。

示例代码

抽象产品:魂灵

//魂灵
public interface Soul {
    //提供什么类型魂环
    String produceSoulRing();
    //提供魂环数量
    int produceSoulRingNum();
}

具体产品:不同类型的魂灵

public class Soul10 implements Soul{
    @Override
    public String produceSoulRing() {
        return "白色魂灵";
    }
    @Override
    public int produceSoulRingNum() {
        return 1;
    }
}
public class Soul10w implements Soul{
    @Override
    public String produceSoulRing() {
        return "红色魂灵";
    }

    @Override
    public int produceSoulRingNum() {
        return 4;
    }
}

抽象工厂:传灵塔

public interface SoulPagodaFactory {
    Soul makeSoul();//制造魂灵
}

具体工厂:传灵塔的魂灵生产线

public class SoulPagodaRing10 implements SoulPagodaFactory{
    @Override
    public Soul makeSoul() {
        System.out.println("制造白色魂灵");
        return new Soul10();
    }
}
public class SoulPagodaRing1w implements SoulPagodaFactory{
    @Override
    public Soul makeSoul() {
        System.out.println("制造黑色魂灵");
        return new Soul1w();
    }
}

魂师进入传灵塔购买需要的魂灵获取魂环

 //唐三想要购买万年魂灵
SoulPagodaRing1w sp1w = new SoulPagodaRing1w();
Soul s1 = sp1w.makeSoul();
System.out.println("唐三购买【"+s1.produceSoulRing()+"】可以提供"
                   +s1.produceSoulRingNum()+"个魂环");
//霍雨浩想要购买凶兽魂灵
SoulPagodaRing10wp sp10wp = new SoulPagodaRing10wp();
Soul s2 = sp10wp.makeSoul();
System.out.println("霍雨浩购买【"+s2.produceSoulRing()+"】可以提供"
                   +s2.produceSoulRingNum()+"个魂环");
//唐舞麟想要购买十万年魂灵
SoulPagodaRing10w sp10w = new SoulPagodaRing10w();
Soul s3 = sp10w.makeSoul();
System.out.println("唐舞麟购买【"+s3.produceSoulRing()+"】可以提供"
                   +s3.produceSoulRingNum()+"个魂环");
//蓝轩宇想要购买百万年魂灵
SoulPagodaRing100w sp100w = new SoulPagodaRing100w();
Soul s4 = sp100w.makeSoul();
System.out.println("蓝轩宇购买【"+s4.produceSoulRing()+"】可以提供"
                   +s4.produceSoulRingNum()+"个魂环");

运行结果

制造黑色魂灵

唐三购买【黑色魂灵】可以提供4个魂环

制造橙色魂灵

霍雨浩购买【橙色魂灵】可以提供12个魂环

制造红色魂灵

唐舞麟购买【红色魂灵】可以提供4个魂环

制造金色魂灵

蓝轩宇购买【红色魂灵】可以提供4个魂环

抽象工厂模式

创建一系列对象,而无需指定具体的实现类。

抽象工厂模式是工厂方法模式的升级,同样包括抽象工厂、具体工厂、抽象产品、具体产品四种角色。

相比工厂方法模式:

抽象工厂模式针对的是多个产品的等级结构,而工厂方法模式只是针对一个产品的等级结构。

抽象工厂模式中产品衍生于不同的接口或抽象类,而工厂方法模式衍生于同一个接口或实现类。

工厂方法模式,每增加一个新产品,就需要建立一座新的工厂。例如传灵塔每增加一种新魂灵的供应,就需要开辟新的魂灵生产线。

而抽象工厂模式,相当于在工厂类之上,再抽象出了一个超级工厂,将不同的产品工厂组合在一起,拓展出了产品族的概念,保证用户始终在一个产品组里面获得产品。同时,也方便管理者对于产品的约束管理。

所以,对于抽象工厂:

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

示例

随着时代的发展,斗罗大陆上出现了无数新的职业,比如魂师、机甲师、锻造师、战舰指挥等,作为大陆第一学院的史莱克学院,同样需要与时俱进,不能只培养魂师。

这就形成一个类似抽象工厂模式的例子。

我们把学校提取出来,上升一下,担任抽象工厂的角色。

斗罗大陆不可能只有一座学院,一座学院也不可能只教授一种职业。

所以,大陆上不仅有史莱克学院,还有日月皇家魂导师学院。这就是具体工厂的角色。

同样,不同的人从事不同的职业,来自不同的学院。

这些职业就是抽象的产品,而每个人就是具体的产品。

示例代码

先创建学校的接口,有两个方法培养魂师,培养机甲师。

public interface University {
    SoulMaster trainSoulMaster();//培养魂师
    Mecha trainMecha();//培养机甲师
}

分别创建史莱克学院和日月皇家魂导师学院

//史莱克学院
public class ShrekUiversity implements University{
    @Override
    public SoulMaster trainSoulMaster() {
        return new ShrekSoulMaster();
    }
    @Override
    public Mecha trainMecha() {
        return new ShrekMecha();
    }
}
//日月皇家魂导师学院
public class RoyalUniversity implements University{
    @Override
    public SoulMaster trainSoulMaster() {
        return new RoyalSoulMaster();
    }
    @Override
    public Mecha trainMecha() {
        return new RoyalMecha();
    }
}

创建魂师和机甲师的职业接口

//魂师
public interface SoulMaster {
    void getSoulMaster();
}
//机甲师
public interface Mecha {
    void getMecha();
}

创建史莱克学院培训出来的魂师和机甲师。

创建日月皇家魂导师学院培训出来的魂师和机甲师。(省略部分代码)

public class ShrekSoulMaster implements SoulMaster{
    @Override
    public void getSoulMaster() {
        System.out.println("史莱克学院的魂师");
    }
}

public class RoyalMecha implements Mecha{
    @Override
    public void getMecha() {
        System.out.println("日月皇家魂导师学院的机甲师");
    }
}

不同的人进入不同的学院,学习不同的职业。

//创建史莱克学院
 ShrekUiversity shrekUiversity = new ShrekUiversity();
//培养魂师
shrekUiversity.trainSoulMaster().getSoulMaster();
//培养机甲师
shrekUiversity.trainMecha().getMecha();
//创建日月皇家魂导师学院
RoyalUniversity royalUniversity = new RoyalUniversity();
//培养魂师
 royalUniversity.trainSoulMaster().getSoulMaster();
//培养机甲师
royalUniversity.trainMecha().getMecha();

运行结果

史莱克学院的魂师

史莱克学院的机甲师

日月皇家魂导师学院的魂师

日月皇家魂导师学院的机甲师

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表