简单工厂模式&策略模式-简介与区别
前言:两种模式的相似点与不同点
不得不说,这两种模式真的很像。
相似点:都用到了面向对象的继承、多态、抽象,都拥有相似的结构。
不同点:工厂模式仅提供具体的实例对象,怎么使用这个对象是client的自由,策略模式client可以通过策略类来决定使用哪个实例的哪个方法。
一、两种模式的公共相同部分
下面,我们假设有一台红白机,里面有一些游戏,每个游戏拥有play(玩)和uninstall(卸载)两个方法。
按照工厂和策略模式,我们抽象出来一个Game接口:
public interface Game {
void play();
void uninstall();
}
然后,我们假设游戏机里有魂斗罗、马戏团、默认的俄罗斯方块三款游戏,每个游戏有不同的玩法和卸载算法:
// 魂斗罗,实现Game
public class Hundouluo implements Game {
@Override
public void play() {
System.out.println("游戏:魂斗罗...playing");
}
@Override
public void uninstall() {
System.out.println("游戏:魂斗罗...卸载");
}
}
// 马戏团,实现Game
public class Maxituan implements Game {
@Override
public void play() {
System.out.println("游戏:马戏团...playing");
}
@Override
public void uninstall() {
System.out.println("游戏:马戏团...卸载");
}
}
// 默认的俄罗斯方块,实现Game
public class Default implements Game {
@Override
public void play() {
System.out.println("游戏:俄罗斯方块...playing");
}
@Override
public void uninstall() {
System.out.println("游戏:俄罗斯方块...卸载");
}
}
ok,工厂模式和策略模式的相同部分就已经写好了,通过上面的代码,我们可以发现这两种模式都是需要把相同的部分抽象出来,通过多态来实例化不同的对象,调用其对应的实现。
二、两种模式的不同部分的实现
2.1:工厂模式
工厂需要一个工厂类,用来返回具体的实例对象用,代码如下:
public class GameFactory {
public static Game getGame(String name) {
switch (name) { //根据传来的游戏名(这里偷懒用了首字母),来实例化具体的对象
case "hdl":
return new Hundouluo();
case "mxt":
return new Maxituan();
default:
return new Default();
}
}
}
2.2:策略模式
策略模式需要策略类来封装具体的行为(方法),并且还可以指定使用哪个实例的哪个行为,代码如下:
// 为了和工厂做充分的区分,这里定义了两个类型的context,分别维护一个行为算法(也就是方法函数,其次建立两个context是为了说明问题,实际使用时可能不需要这么多)
// 用来维护play这个算法的实现
public class PlayContext {
private Game game;
public PlayContext() {
this.game = new Default();
}
public PlayContext(Game game) {
this.game = game; // 这里根据传入的具体实例赋值
}
public void trigger() {
this.game.play(); // 这里是对行为的封装,只提供play方法的触发
}
}
// 用来维护uninstall这个算法的实现
public class UninstallContext {
private Game game;
public UninstallContext() {
this.game = new Default();
}
public UninstallContext(Game game) {
this.game = game; // 这里根据传入的具体实例赋值
}
public void trigger() {
this.game.uninstall(); // 这里是对行为的封装,只提供uninstall方法的触发
}
}
测试代码:
new PlayContext(new Hundouluo()).trigger();
new UninstallContext(new Hundouluo()).trigger();
new PlayContext(new Maxituan()).trigger();
new UninstallContext(new Maxituan()).trigger();
运行结果:
游戏:魂斗罗...playing
游戏:魂斗罗...卸载
游戏:马戏团...playing
游戏:马戏团...卸载
通过上面的实验,和对比,会发现,工厂模式是简单的对实例的封装,而策略模式更在意的是对具体实例的具体行为(方法)的封装。
还有一种情况就是利用工厂模式的思想,实现的策略模式,我们现在来改造下上面的PlayContext源码:
public class PlayContext {
private Game game;
public PlayContext() {
this.game = new Default();
}
public PlayContext(String name) {
switch (name) { //根据传来的游戏名(这里偷懒用了首字母),来实例化具体的对象
case "hdl":
this.game = new Hundouluo();
break;
case "mxt":
this.game = new Maxituan();
break;
default:
this.game = new Default();
}
}
public void trigger() {
this.game.play(); // 这里是对行为的封装,只提供play方法的触发
}
}
测试类:
new PlayContext("hdl").trigger();
new UninstallContext(new Hundouluo()).trigger();
new PlayContext("mxt").trigger();
new UninstallContext(new Maxituan()).trigger();
测试结果:
游戏:魂斗罗...playing
游戏:魂斗罗...卸载
游戏:马戏团...playing
游戏:马戏团...卸载
三、总结
策略模式是一种定义一系列算法的方法,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有算法,减少了各种算法类与使用算法类之间的耦合。
工厂模式仅提供对应的实例,不对其方法做封装,减少了具体实现的实例与使用实例的业务方的耦合。
(↑描述待改进)
简单工厂模式&策略模式-简介与区别的更多相关文章
- 工厂模式&策略模式。
抽象.封装,具体事情做得越多,越容易犯错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,犯错误可能性就越少.好象我们从编程序中也能悟出人生道理.(百度百科) 不断抽象封装 ...
- 3.js模式-策略模式
1. 策略模式 策略模式定义一系列的算法,把它们封装起来,并且可以互相替换. var strategies = { isNonEmpty: function(value,errMsg){ if(val ...
- 命令模式 & 策略模式 & 模板方法
一.策略模式 策略模式:封装易变化的算法,可互相替换. GoF<设计模式>中说道:定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换.该模式使得算法可独立于它们的客户变化. 比如 ...
- [C#]设计模式-简单工厂-创建型模式
在设计模式当中有三大工厂,分别是 简单工厂.抽象工厂.工厂方法 这三种创建实例的设计模式,这里先从简单工厂将其,从名字就可以看出这是这三种工厂模式当中最为简单的一种实现. 简单工厂一般由以下几个对象组 ...
- <大话设计模式>工厂模式,策略模式
第一章:工厂模式: 通过封装,继承,多态解耦合 业务逻辑和界面逻辑分开 用单独的类创造实例,工厂:创造实例 工厂模式还可以用反射来实现,nsstringFromClass UML类图 聚合表示一众弱的 ...
- 模板方法模式&策略模式区别联系
一.模板方法 模板方法模式:定义 一系列算法, 子类延伸实现.着重点在于:子类去处理不同的方法实现. 看下面例子. 假如一个支付 都包含三个部分: 生成订单 ---->调用API发起支付---- ...
- 设计模式之——浅谈strategy模式(策略模式)
strategy模式,即策略模式.个人觉得吧,策略模式更多的是一种思维方式. 首先我们要知道,为什么需要策略模式.举个例子,比如用程序输出今天下午去玩什么. PlayGame 玩游戏 package ...
- Go---设计模式(策略模式)
策略模式定义了算法家族,在调用算法家族的时候不感知算法的变化,客户也不会受到影响. 下面用<大话设计模式>中的一个实例进行改写. 例:超市中经常进行促销活动,促销活动的促销方法就是一个个策 ...
- [Python模式]策略模式
策略模式 定义了算法族,分别封装起来,让它们之间可以互相替换.此模式让算法的变化独立于使用算法的客户. 作为动态语言,Python实现策略模式非常容易,只要所有算法提供相同的函数即可. import ...
随机推荐
- tomcat启动了server.xml中没有配置的项目
在tomcat的conf目录下的server.xml文件中没有配置hczm_struts项目,但在eclipse启动tomcat调试时,一直启动hczm_struts项目. 经检查,发现conf\Ca ...
- cpuinfo
在Linux系统中,如何详细了解CPU的信息呢? 当然是通过cat /proc/cpuinfo来检查了,但是比如几个物理CPU/几核/几线程,这些问题怎么确定呢? 经过查看,我的开发机器是1个物理CP ...
- Interceptor for {http://cxf.liuyang.com/}IHiServiceService has thrown exception, unwinding now org.apache.cxf.binding.soap.SoapFault: Error reading XMLStreamReader.
Jquery同域访问:客户端连接服务器访问跨域访问:通过本地html文档,浏览器点击开访问(jquery不支持此访问) 用域名的方式访问http://localhost:8080/CXF_09_jqu ...
- BASE64Encoder及BASE64Decoder编译器找不到问题
编译器自带这两个类,但是会报错找不到,需要手动让编译器识别这个类 第一步.右键项目,然后选择properties 第二步,打开如图位置 第三部,选择如图位置,双击 第四部,add添加 更改值 改为如图 ...
- swift 动画
// // ViewController.swift // Anamation // // Created by su on 15/12/9. // Copyright © 2015年 tia ...
- SQL描述(2)
很久之前就想写出来,就是因为自己太懒,憋了怎么久.本文关于使用ORACLE分析函数对一些经济指标进行计算.表indi_value有3个关键的字段:indi_date,indi_value,indi_i ...
- 10-10Linux的文件操作函数以及所需头文件
Linux的基本文件操作函数 Linux通过相应的对文件的IO函数来实现对文件的操作,这些函数通常被称作"不带缓冲的IO",这是因为他们都是通过调用Linux的内核调用来实 ...
- PostgreSQL查询数据(连接查询和子查询)
原料 --用户表 create table "SysUser"( "UserId" serial, --用户Id,自增 "UserName" ...
- AppDomain.CurrentDomain.BaseDirectory项目目录相关操作
链接:https://www.cnblogs.com/guolianyu/p/3980971.html 经常用到,每次都百度,所以自己备份一下!
- 4-C#格式处理
本篇博客对应视频讲解 前言 前几篇文章及对应视频是带大家快速体验了一下C#,了解编程语言最基础的内容及面向对象的概念. 接下来我会进一步演示和说明C#还能做些什么. 实际上,C#就一门语言来讲,除去面 ...