对设计模式的总结之简单工厂与策略模式

前言

面向对象编程追求的本质-提高扩展性、可维护性、灵活性和复用性。合理利用面向对象6个原则,能够很好的达到要求。如何利用好就是至关重要的了,前人总结了23+个设计模式能够让初学者更容易学到其中的精髓,本文就说说我对本人对简单工厂模式、策略模式的见解。

简单工厂模式与策略模式

简单工厂模式

工作中,常常遇到需要做一个功能(鸭子),这个功能中含有可控个数的子操作功能(鸭子叫,鸭子跑,鸭子飞),而且子功能在不同的情况下处理方式又不相同(成年鸭子/小鸭子叫,成年鸭子/小鸭子跑,成年鸭子/小鸭子飞)。我们首先就会想到,用简单工厂模式哇。创建一个该功能的抽象基类,再创建多个实现不同逻辑的子类继承它。最后建立一个工厂类,通过工厂类中类型判断可生成不同的该功能子类实例。客户端最后调用工厂和抽象基类操作即可。实现类与类松耦合,既简单又实用。

基本用法

  1.     /// <summary>
        /// 工厂类
        /// </summary>
        public class GameOfInteractive
        {
            /// <summary>
            /// 游戏返回基类
            /// </summary>
            private static GameAbstract gameServiceCall = null;
    
            /// <summary>
            /// 工厂构造类
            /// </summary>
            /// <param name="gameType"></param>
            public static GameAbstract GameService(int gameType)
            {
                try
                {
                    switch (gameType)
                    {
                        case 1:
                            gameServiceCall = new Sparrow();
                            break;
                        case 2:
                            gameServiceCall = new ShootBirds();
                            break;
                        default:
                            break;
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                return gameServiceCall;
            }
        }
    
        /// <summary>
        /// 抽象基类
        /// </summary>
        public abstract class GameAbstract
        {
    
            /// <summary>
            /// 游戏登录
            /// </summary>
            /// <param name="sLoginName"></param>
            /// <param name="sPsw"></param>
            /// <returns></returns>
            public abstract string Login(string sLoginName, string sPsw);
    
            /// <summary>
            /// 游戏退出
            /// </summary>
            /// <param name="sLoginName"></param>
            /// <param name="sPsw"></param>
            /// <returns></returns>
            public abstract string LoginOut(string sLoginName, string sPsw);
        }
    
        /// <summary>
        /// XX游戏具体类
        /// </summary>
        public class ShootBirds: GameAbstract
        { /// <summary>
          /// 游戏登录
          /// </summary>
          /// <param name="sLoginName"></param>
          /// <param name="sPsw"></param>
          /// <returns></returns>
            public override string Login(string sLoginName, string sPsw)
            {
                return "我通过HTTP请求和XX游戏服务交互进行登录";
            }
    
            /// <summary>
            /// 游戏退出
            /// </summary>
            /// <param name="sLoginName"></param>
            /// <param name="sPsw"></param>
            /// <returns></returns>
            public override string LoginOut(string sLoginName, string sPsw)
            {
                return "我通过HTTP请求和XX游戏服务交互,传输sLoginName和sPsw,通知客户下线";
            }
        }
    
        /// <summary>
        /// YY游戏操作类
        /// </summary>
        public class Sparrow : GameAbstract
        {
            /// <summary>
            /// 游戏登录
            /// </summary>
            /// <param name="sLoginName"></param>
            /// <param name="sPsw"></param>
            /// <returns></returns>
            public override string Login(string sLoginName, string sPsw)
            {
                return "我通过socket和YY游戏服务交互进行登录";
            }
    
            /// <summary>
            /// 游戏退出
            /// </summary>
            /// <param name="sLoginName"></param>
            /// <param name="sPsw"></param>
            /// <returns></returns>
            public override string LoginOut(string sLoginName, string sPsw)
            {
                return "我通过socket和YY游戏服务交互,传输sLoginName和sPsw,通知客户下线";
            }
        }

总结

优缺点:工厂模式初步满足了开放-封闭原则;工厂的使用,降低了对象之间的耦合性,做到了责任分离(客户端不直接创建对象实例,生产实例交给工厂来做)。

工厂与消费者、原料间的联系都很紧,如果工厂出了问题,与之相关的所有功能都将瘫痪;每次功能扩展,都需要改动工厂类,违反了高内聚责任分配原则。

使用场景:一般只在很简单的情况下应用。eg:多数据库选择,登录系统与其他系统做简单信息交互操作等。

策略模式

万物随时变,唯一不变的就是变化。实体经济萧条,商场生意不如以往,不想被拍死在沙滩上,就必须增加新的刺激消费的活动 。eg:满100返10,满500送自行车,会员卡送积分(积分可以换商品),多级会员打折等促销等方式。这些促销方式不是一次性就定下来的,是随着时间的改变产生的,如果在商场计价系统中直接用简单工厂模式,算法经常更改,工厂也随之更改,维护和扩展成本都会逐步增加。考虑到计价功能单一,每个子功能都只做计价,结构固定。可以把具体使用那种计价方式的任务交给客户端来控制,这样就产生了策略模式。策略模式与简单工厂模式很像,都有功能基类和各种扩展的子功能类,唯一不同的就是策略模式强调的是算法封装,不同的算法,用相应的子类进行实现

基本用法

  1. /// <summary>
        /// 环境角色
        /// </summary>
        public class Context
        {
            /// <summary>
            /// 需要的策略
            /// </summary>
            private AbstractStrategy strategy = null;
    
            /// <summary>
            /// 计算实际得到工资
            /// </summary>
            /// <param name="overtime"></param>
            /// <returns></returns>
            public decimal CalculateSalary(int overtime)
            {
                return strategy.CalculateSalary(overtime);
            }
        }
        /// <summary>
        /// 抽象策略角色
        /// </summary>
        public abstract class AbstractStrategy
        {
    
            protected  static int baseOvertime = 80;//每个月基础加班时间
    
            /// <summary>
            /// 计算实际得到工资
            /// </summary>
            /// <param name="overtime">加班时间</param>
            /// <returns></returns>
            public abstract decimal CalculateSalary(int overtime);
        }
        /// <summary>
        /// 工人工资计算
        /// </summary>
        public class WagesForWorkmen:AbstractStrategy
        {
            private static decimal baseSalary = 2800;//基础工资
    
            private static decimal overtimeSalary = 37.5M;//每小时加班费
    
            private static decimal extraSubsidies = 8.6M;//超出基础加班时间后每小时另加补助费用
    
            /// <summary>
            /// 计算实际得到工资
            /// </summary>
            /// <param name="overtime">加班时间</param>
            /// <returns></returns>
            public override  decimal CalculateSalary(int overtime)
            {
                decimal actuallySalary = baseSalary;
                if (overtime> baseOvertime)
                {
                    actuallySalary += overtimeSalary * baseOvertime + (overtime - baseOvertime) * (overtimeSalary + extraSubsidies);
                }
                else
                {
                    actuallySalary += overtimeSalary * overtime;
                }
                return actuallySalary;
            }
        }
        /// <summary>
        /// 组长工资计算
        /// </summary>
        public class WagesForGroupLeader:AbstractStrategy
        {
            private static decimal baseSalary = 2800;//基础工资
    
            private static decimal postSalary = 800;//岗位工资
    
            private static decimal overtimeSalary = 40M;//每小时加班费
    
            private static decimal extraSubsidies = 5M;//超出基础加班时间后每小时另加补助费用
    
            /// <summary>
            /// 计算实际得到工资
            /// </summary>
            /// <param name="overtime">加班时间</param>
            /// <returns></returns>
            public override decimal CalculateSalary(int overtime)
            {
                decimal actuallySalary = baseSalary+ postSalary;
                if (overtime > baseOvertime)
                {
                    actuallySalary += overtimeSalary * baseOvertime + (overtime - baseOvertime) * (overtimeSalary + extraSubsidies);
                }
                else
                {
                    actuallySalary += overtimeSalary * overtime;
                }
                return actuallySalary;
            }
        }
        /// <summary>
        /// 经理工资计算
        /// </summary>
        public class WagesForManager : AbstractStrategy
        {
            private static decimal baseSalary = 8000;//基础工资
    
            private static decimal overtimeSalary =80M;//每小时加班费
    
            private static decimal extraOvertimeSalary = 0M;//超出基础加班时间后每小时加班费
            /// <summary>
            /// 计算实际得到工资
            /// </summary>
            /// <param name="overtime">加班时间</param>
            /// <returns></returns>
            public override decimal CalculateSalary(int overtime)
            {
                decimal actuallySalary = baseSalary;
                if (overtime > baseOvertime)
                {
                    actuallySalary += overtimeSalary * baseOvertime + (overtime - baseOvertime) * extraOvertimeSalary;
                }
                else
                {
                    actuallySalary += overtimeSalary * overtime;
                }
                return actuallySalary;
            }
        }

总结

优缺点:相对于简单工厂模式,能避免工厂挂掉,其他相应功能都被牵连的问题;能满足客户端高频率更换功能实现算法要求(不用总是去改工厂类,只需要在客户端更改调用类)。

策略模式适用于客户端知道所有的算法或行为的情况,增加了具体功能与客户端的耦合度。

使用场景:商场计价功能、税收计算功能、保险行业的参保收益计价功能。

简单工厂与策略结合

使用简单工厂时,客户端需要知道工厂类和功能基类;基本的策略模式,将选择所用具体实现的职责交给客户端,本身没有减除客户端需要选择判断的压力。能否进优化?可以。将两者结合起来,让环境角色(StrategyContext)拥有选择策略和执行策略两种功能,客户端只需要传递类型参数调用环境角色即可。

基本用法

  1. /// <summary>
        /// 环境角色
        /// </summary>
        public class Context
        {
            /// <summary>
            /// 需要的策略
            /// </summary>
            private AbstractStrategy strategy = null;
    
            /// <summary>
            /// 获取策略
            /// </summary>
            /// <returns></returns>
            public Context(int iType)
            {
                switch (iType)
                {
                    case 1:
                        strategy = new WagesForWorkmen();
                        break;
                    case 2:
                        strategy = new WagesForGroupLeader();
                        break;
                    case 3:
                        strategy = new WagesForManager();
                        break;
                }
            }
    
            /// <summary>
            /// 计算实际得到工资
            /// </summary>
            /// <param name="overtime"></param>
            /// <returns></returns>
            public decimal CalculateSalary(int overtime)
            {
                return strategy.CalculateSalary(overtime);
            }
        }

总结

优缺点:相对于简单工厂模式、单一策略模式,进一步实现了解耦(客户端只需和环境角色交互)。

虽然进一步解耦,但是任然存在简单工厂的问题。

时间: 2024-10-02 04:30:33

对设计模式的总结之简单工厂与策略模式的相关文章

简单工厂与策略模式

简单工厂模式 专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类.它又称为静态工厂方法模式,属于类的创建型模式.简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例. 该模式中包含的角色及其职责: 1.工厂(Creator)角色 简单工厂模式的核心,它负责实现创建所有实例的内部逻辑.工厂类可以被外界直接调用,创建所需的产品对象. 2.抽象(Product)角色 简单工厂模式所创建的所有对象的父类,它负责描述所有实

设计模式(一)——简单工厂模式

嵌入式linux 设计模式(一)--简单工厂模式 一.简单工厂模式简介 1.简单工厂模式 简单工厂模式(Factory Method Pattern)是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例. 简单工厂模式的UML类图 工厂角色(Creator):是简单工厂模式的核心,由它负责创建所有的类的内部逻辑.工厂类必须能够被

设计模式粗浅理解之一------简单工厂模式

设计模式粗浅理解之------简单工厂模式 什么是简单工厂模式 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一.简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例.简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现. 角色和职责 工厂(Creator)角色 简单工厂模式的核心,它负责实现创建所有实例的内部逻辑.工厂类可以被外界直接调用,创建所需的产

大话设计模式读书笔记1——简单工厂模式

最近几日,重温了一下<大话设计模式>这本书,当时读的仓促,有很多没有注意的地方,现在仔细翻看起来,发现这值得细细品味的一本书!! 好东西就要记下来!!! 第一章笔记:从一个简单的计算器程序来看简单工厂模式. 变化的地方就要封装,用一个单独的类来做创造实例的过程这就是工厂. UML图: /// <summary> /// 运算类 /// </summary> public class Operation { public double Number1 { get; set

Java设计模式(一) 简单工厂模式不简单

原创文章,转载请务必将下面这段话置于文章开头处. 本文转发自Jason's Blog,原文链接 http://www.jasongj.com/design_pattern/simple_factory 简单工厂模式使用案例 有一种抽象产品--汽车(Car),同时有多种具体的子类产品,如BenzCar,BMWCar,LandRoverCar.类图如下 作为司机,如果要开其中一种车,比如BenzCar,最直接的做法是直接创建BenzCar的实例,并执行其drive方法,如下 package com.

设计模式系列一(简单工厂VS工厂方法)

1.简单工厂简介 诞生背景:在我们平常编程当中,经常会使用new进行实例化一个对象,此时该类完全依赖于该对象,专业术语来说就是耦合度高.当需求发生变化时我们不得不去修改此类的源码,造成整个系统难以维护!然而面向对象(oo)一个很重要的原则(封装变化)就可以解决这样一个问题:那既然要封装变化,自然要找到改变的代码,然后把改变的代码用类进行封装.这样一个思路就引出了简单工厂模式. 定义:简单工厂模式又叫静态工厂模式,顾名思义,它是用来实例化对象类的静态类. 2.简单工厂实例 /// <summary

简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别

结合简单示例和UML图,讲解工厂模式简单原理. 一.引子 话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰).Bmw(宝马).Audi(奥迪)),还雇了司机为他开车.不过,爆发户坐车时总是这样:上Benz车后跟司机说"开奔驰车!",坐上Bmw后他说"开宝马车!",坐上 Audi后他说"开奥迪车!".你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的!幸运的是这种有

(转)设计模式(五)简单工厂模式+工厂方法模式

在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的.但是在一些情况下, new操作符直接生成对象会带来一些问题.举例来说, 许多类型对象的创造需要一系列的步骤: 你可能需要计算或取得对象的初始设置; 选择生成哪个子对象实例; 或在生成你需要的对象之前必须先生成一些辅助功能的对象. 在这些情况,新对象的建立就是一个 “过程”,不仅是一个操作,像一部大机器中的一个齿轮传动. 模式的问题:你如何能轻松方便地构造对象实例,而不必关心构造对象实例的细节和

设计模式笔记1:简单工厂模式

如果想成为一名更优秀的软件设计师,了解优秀软件设计的演变过程比学习优秀设计本身更有价值. 1.1 面向对象的好处 通过封装.继承多态把程序的耦合度降低,使用设计模式使得程序更加灵活,容易修改,易于复用. 1.2  类图 1.3 代码 几个运算类: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks;