前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >简单工厂模式和策略模式的区别

简单工厂模式和策略模式的区别

作者头像
chenchenchen
发布2021-09-06 14:15:30
5.2K0
发布2021-09-06 14:15:30
举报
文章被收录于专栏:chenchenchen

对比

简单工厂模式和策略模式都是三个业务子类继承抽象父类,通过传入参数到容器类(工厂模式的factory类,策略模式的Content类),选择对应的类进行行为操作。

其实,UML图的确从外形上看没多大区别,但是,本质却是大大不同。

简单工厂模式

简单工厂模式客户端传一个条件进工厂类,工厂类根据条件生成相应的对象并返回给客户端。实质是由一个工厂类根据传入的参数,动态决定应该创建并且返回哪一个产品类(这些产品类继承自一个父类或接口)的实例。

那么也就是说:

1、有已知的产品类

2、你无法准确的知道编译哪个产品类

3、需要在运行时决定创建哪个产品类

4、产品类不多

很明显看出,在创建对象上的灵活性高,但是工厂类只能创建可能会使用到的产品类,假如新添了产品类就得修改工厂类,这样就会违反开闭原则。

策略模式

客户端创建一个Context对象a,创建策略对象并当做参数传递给a,然后客户端使用a方法通过某种方法得到想要的值返回给客户端。

策略模式是行为型模式,它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

在一段代码里,使用了逻辑控制(if-else,swich-case)来决定算法,算法有相似的方法和函数,就可以选择策略模式。

那么也就是说:

1、某方法里有多个条件语句,条件语句代码块里有许多行为过程。

2、其算法能封装到策略类

2、算法随意切换

3、算法与客户端隔离

这样一来,通过选择对应的策略类,作为参数传到Content类里,在运行时配置对应的算法。

差异

如果在适合用策略模式的情况下用简单工厂模式,如果新增加策略就要修改工厂类,而这个可能会导致其他错误和比较繁琐,而如果使用了策略模式,只要将新增加的策略当做参数传递到Context类中即可。

  • 用途不一样 工厂是创建型模式,它的作用就是创建对象; 策略是行为型模式,它的作用是让一个对象在许多行为中选择一种行为;
  • 关注点不一样 一个关注对象创建 一个关注行为的封装
  • 解决不同的问题 工厂模式是创建型的设计模式,它接受指令,创建出符合要求的实例;它主要解决的是资源的统一分发,将对象的创建完全独立出来,让对象的创建和具体的使用客户无关。主要应用在多数据库选择,类库文件加载等。 策略模式是为了解决的是策略的切换与扩展,更简洁的说是定义策略族,分别封装起来,让他们之间可以相互替换,策略模式让策略的变化独立于使用策略的客户。
  • 工厂相当于黑盒子,策略相当于白盒子;

代码实现

先写一个人的接口类,有eat,run,wear 3个方法

代码语言:javascript
复制
public interface People {
 
    public void eat();
 
    public void run();
 
    public void wear();
}

分别写两个实现类,一个是小明的实现类,一个是小红的实现类

代码语言:javascript
复制
public class Xiaoming implements People{
 
    @Override
    public void eat() {
        System.out.println("小明吃饭");
    }
 
    @Override
    public void run() {
        System.out.println("小明跑步");
    }
 
    @Override
    public void wear() {
        System.out.println("小明穿衣");
    }
}
 
 
public class Xiaohong implements People{
 
    @Override
    public void eat() {
        System.out.println("小红吃饭");
    }
 
    @Override
    public void run() {
        System.out.println("小红跑步");
    }
 
    @Override
    public void wear() {
        System.out.println("小红穿衣");
    }
}

简单工厂模式的代码

代码语言:javascript
复制
public class PeopleFactory {
 
    public People getPeople(String name){
        if(name.equals("Xiaoming")){
            return new Xiaoming();
        }else if(name.equals("Xiaohong")){
            return new Xiaohong();
        }
        return null;
    }
}

再来看下策略模式的代码

代码语言:javascript
复制
public class StrategySign {
 
    private People people;
 
    public StrategySign(People people){
        this.people = people;
    }
 
    public StrategySign(String name){
        if(name.equals("Xiaoming")){
            this.people = new Xiaoming();
        }else if(name.equals("Xiaohong")){
            this.people = new Xiaohong();
        }
    }
 
    public void run(){
        people.run();
    }
}

策略模式的两种构造方法都可以用,我多写了一种是为了让大家看到和工厂模式的区别和联系

然后我们通过测试类运行两种模式

代码语言:javascript
复制
@Test
    public void testSign(){
        PeopleFactory peopleFactory = new PeopleFactory();
        People people = peopleFactory.getPeople("Xiaohong");
        System.out.print("工厂模式-------------"); people.run();
        StrategySign strategySign = new StrategySign("Xiaohong");
        System.out.print("策略模式-------------");strategySign.run();
    }

可以看到,两种设计模式的运行结果是一模一样的,那么区别到底在哪呢。

从工厂模式的代码中可以看到 工厂模式主要是返回的接口实现类的实例化对象,最后返回的结果是接口实现类中的方法,而策略模式是在实例化策略模式的时候已经创建好了,我们可以再策略模式中随意的拼接重写方法,而工厂模式是不管方法的拼接这些的,他只关注最后的结果,不注重过程,而策略模式注重的是过程。

用一个具体的例子可以看下,如果我想小红先吃饭再跑步再吃饭的话,那么我需要在测试类中写3种,而我只需要在策略模式的方法中直接定义即可。

可以看以下代码:

代码语言:javascript
复制
public class StrategySign {
 
    private People people;
 
    public StrategySign(People people){
        this.people = people;
    }
 
    public StrategySign(String name){
        if(name.equals("Xiaoming")){
            this.people = new Xiaoming();
        }else if(name.equals("Xiaohong")){
            this.people = new Xiaohong();
        }
    }
 
    public void run() {
        people.eat();
        people.run();
        people.eat();
    }
}
 
@Test
    public void testSign(){
        PeopleFactory peopleFactory = new PeopleFactory();
        People people = peopleFactory.getPeople("Xiaohong");
        System.out.print("工厂模式-------------"); people.eat();
        System.out.print("工厂模式-------------"); people.run();
        System.out.print("工厂模式-------------"); people.eat();
        StrategySign strategySign = new StrategySign("Xiaohong");
        System.out.print("策略模式-------------");strategySign.run();
    }

结合

下面有一段策略模式的代码。

代码语言:javascript
复制
using System;
using System.Net.Configuration;

namespace StrategyWithFactory
{
    class Program
    {
        static void Main(string[] args)
        {
            Strategy strategyContent = null;

            //伪代码。获取输入算法类型
            EStrategy inputType = RequestInput();

            if (inputType == EStrategy.A)
            {
                new Content(new StrategyA()).ContentInterface();
            }
            else if (inputType == EStrategy.B)
            {
                new Content(new StrategyB()).ContentInterface();
            }
            else if (inputType == EStrategy.C)
            {
                new Content(new StrategyC()).ContentInterface();
            }
        }
    }

    //算法抽象类
    abstract class Strategy
    {
        public abstract void AlfoeirhmInterface();
    }

    //A算法类
    class StrategyA : Strategy
    {
        public override void AlfoeirhmInterface()
        {
            Console.WriteLine("this is the StrategyA");
        }
    }

    //B算法类
    class StrategyB : Strategy
    {
        public override void AlfoeirhmInterface()
        {
            Console.WriteLine("this is the StrategyB");
        }
    }

    //B算法类
    class StrategyC : Strategy
    {
        public override void AlfoeirhmInterface()
        {
            Console.WriteLine("this is the StrategyC");
        }
    }

    //上下文类
    class Content
    {
        private readonly Strategy _strategy;
        public Content(Strategy strategy)
        {
            _strategy = strategy;
        }

        public void ContentInterface()
        {
            _strategy.AlfoeirhmInterface();
        }
    }

    //算法枚举
    enum EStrategy
    {
        A = 1,
        B = 2,
        C = 3
    }
}

上面的代码是策略模式的原型,假如Main函数是客户端,那么以后每加一个算法,都得在客户端修改一次,添加一个else if,引起了不必要的麻烦。那么,现在的情况,首先我们知道已有的ABC三种算法,但是我们又不确定运行时使用哪种算法,同时为了让客户端和业务逻辑代码隔离开,于是,我们可以将客户端的创建算法类的业务逻辑转移到Cotent类,并添加一个创建算法工厂的方法。

代码语言:javascript
复制
using System;

namespace StrategyWithFactory
{
    class Program
    {
        static void Main(string[] args)
        {
            //伪代码。获取输入算法类型
            EStrategy inputType = RequestInput();
            new Content(inputType).ContentInterface();
        }
    }

    //上下文类
    class Content
    {
        private readonly Strategy _strategy;
        public Content(EStrategy eStrategy)
        {
            _strategy = CreateFactory(eStrategy);
        }

        public Strategy CreateFactory(EStrategy eStrategy)
        {
            Strategy strategy = null;
            switch (eStrategy)
            {
                case EStrategy.A:
                    strategy = new StrategyA();
                    break;

                case EStrategy.B:
                    strategy = new StrategyB();
                    break;

                case EStrategy.C:
                    strategy = new StrategyC();
                    break;
            }
            return strategy;
        }

        public void ContentInterface()
        {
            _strategy.AlfoeirhmInterface();
        }
    }
}

那么,策略和简单工厂的结合应用就实现了。

小结

工厂模式中只管生产实例,具体怎么使用工厂实例由调用方决定,策略模式是将生成实例的使用策略放在策略类中配置后才提供调用方使用。

工厂模式调用方可以直接调用工厂实例的方法属性等,策略模式不能直接调用实例的方法属性,需要在策略类中封装策略后调用。

策略模式将不同的算法封装成一个对象,这些不同的算法从一个抽象类或者一个接口中派生出来,客户端持有一个抽象的策略的引用,这样客户端就能动态的切换不同的策略。 而工厂模式又分为简单工厂和抽象工厂和工厂模式 ,这些工厂是为了创建对象而出现的,工厂模式创建不同的单个对象,而抽象工厂是为了创建不同的一些列的对象或者操作

工厂模式类似英语考试的完形填空题(自己考虑填什么词、句子),策略模式类似信息匹配题(提前写好选择项,当你有多个填空时,直接选就好了,没有适合的就再多写几个选择项)。

参考:

https://blog.csdn.net/lmx125254/article/details/86625960

https://cloud.tencent.com/developer/article/1334971

https://blog.csdn.net/weixin_39928686/article/details/111124201

https://www.cnblogs.com/me115/p/3790615.html

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/02/10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 对比
    • 简单工厂模式
      • 策略模式
      • 差异
      • 代码实现
      • 结合
      • 小结
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档