《大话设计模式》java实现:第一章-简单工厂模式
在《大话设计模式》中,示例代码使用C#实现,所以我这里使用Java实现一遍书中的设计模式。
第一章是使用简单工厂实现计算器。
遇到了一个问题:在Operation父类中,我们可以定义两个操作数作为成员变量,在类初始化时直接传参,那么GetResult()函数可以直接调用成员变量返回值,而不需要再次传参。也可以不定义成员变量,而是在调用GetRsult()时再传参。那么该如何选择?
- 使用成员变量:需要设置每一个运算子类的初始化函数,并修改工厂类,在工厂类初始化运算类的时候传入两个操作数和运算符。初始化函数这部分都是重复的,且需要额外的空间存储运算符。
package gof;
import java.util.Scanner;
/*
* 《大话设计模式》第一章,简单工厂制作计算器
*/
public class SimpleFactory {
public static void main(String[] args) {
try (//用户界面
Scanner input = new Scanner(System.in)) {
System.out.printf("请输入数字1:");
double number1=input.nextDouble();
System.out.printf("请输入运算符:");
String operator=input.next();
System.out.printf("请输入数字2:");
double number2=input.nextDouble();
System.out.printf("请输入使用哪一个操作:\n1.简单封装\n2.简单工厂模式\n");
int choose=input.nextInt();
switch (choose) {
case 1: {
System.out.printf("答案是:"+simpleEncapsulation(number1, number2, operator));
return;
}
case 2:{
System.out.printf("答案是:"+polymorphsimOperation(number1, number2, operator));
return;
}
default:
throw new IllegalArgumentException("没有这个选项: " + choose);
}
}
}
//使用简单封装
static double simpleEncapsulation(double number1, double number2, String operator) {
return OperationEncapsulation.getResult(number1, number2, operator);
}
//使用简单工厂模式
static double polymorphsimOperation(double number1, double number2, String operator) {
Operation operation=OperationFactory.getOperation(number1,number2,operator);
try {
return operation.getResult();
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
}
/*
* 1.使用客户端与操作分离,简单封装
*/
class OperationEncapsulation{
public static double getResult(double number1, double number2, String operator) {
switch (operator) {
case "+": {
return number1+number2;
}
case "-":{
return number1-number2;
}
case "*":{
return number1*number2;
}
case "/":{
if(number2!=0) return number1+number2;
}
default:
System.out.println("非法运算符:"+operator);
//throw new IllegalArgumentException("非法运算符:" + operator);
}
return 0;
}
}
/*
* 2. 封装,继承,多态
* 使用简单工厂解决多态带来的如何实例化指定类的问题
*/
//父类
abstract class Operation{
double number1;
double number2;
//String operator;
public Operation(double number1, double number2) {
this.number1=number1;
this.number2=number2;
}
public double getNumber1() {
return number1;
}
public void setNumber1(double number1) {
this.number1 = number1;
}
public double getNumber2() {
return number2;
}
public void setNumber2(double number2) {
this.number2 = number2;
}
abstract double getResult();
}
// 加减乘除类
class OperationAdd extends Operation{
public OperationAdd(double number1, double number2) {
super(number1, number2);
}
public double getResult() {
return number1+number2;
}
}
class OperationSub extends Operation{
public OperationSub(double number1, double number2) {
super(number1, number2);
}
public double getResult() {
return number1-number2;
}
}
class OperationMul extends Operation{
public OperationMul(double number1, double number2) {
super(number1, number2);
}
public double getResult() {
return number1*number2;
}
}
class OperationDiv extends Operation{
public OperationDiv(double number1, double number2) {
super(number1, number2);
}
public double getResult() {
if (number2==0) {
return 0;
}
return number1/number2;
}
}
//简单工厂类,判断实例化哪一个子类
class OperationFactory{
static Operation getOperation(Double number1, Double number2, String operator) {
switch (operator) {
case "+": {
return new OperationAdd(number1,number2);
}
case "-": {
return new OperationSub(number1,number2);
}
case "*": {
return new OperationMul(number1,number2);
}
case "/": {
return new OperationDiv(number1,number2);
}
default:
System.out.println("非法运算符:"+operator);
//throw new IllegalArgumentException("非法运算符: " + operator);
}
return null;
}
}
- 不使用成员变量:重复的代码会大幅减少,每个运算类只需要定义GetResult(),但是客户端调用GetResult()的时候需要传两次参,原本只需要把全部参数交给工厂类,只传一次参。
package gof;
import java.util.Scanner;
/*
* 《大话设计模式》第一章,简单工厂制作计算器
*/
public class SimpleFactory {
public static void main(String[] args) {
try (//用户界面
Scanner input = new Scanner(System.in)) {
System.out.printf("请输入数字1:");
double number1=input.nextDouble();
System.out.printf("请输入运算符:");
String operator=input.next();
if (operator!="+"&&operator!="-"&&operator!="*"&&operator!="/") {
System.out.printf("运算符非法,重新输入运算符:");
operator=input.next();
}
System.out.printf("请输入数字2:");
double number2=input.nextDouble();
System.out.printf("请输入使用哪一个操作:\n1.简单封装\n2.简单工厂模式\n");
int choose=input.nextInt();
switch (choose) {
case 1: {
System.out.printf("答案是:"+simpleEncapsulation(number1, number2, operator));
return;
}
case 2:{
System.out.printf("答案是:"+polymorphsimOperation(number1, number2, operator));
return;
}
default:
throw new IllegalArgumentException("没有这个选项: " + choose);
}
}
}
//使用简单封装
static double simpleEncapsulation(double number1, double number2, String operator) {
return OperationEncapsulation.getResult(number1, number2, operator);
}
//使用简单工厂模式
static double polymorphsimOperation(double number1, double number2, String operator) {
Operation operation=OperationFactory.getOperation(operator);
try {
return operation.getResult(number1, number2);
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
}
/*
* 1.使用客户端与操作分离,简单封装
*/
class OperationEncapsulation{
public static double getResult(double number1, double number2, String operator) {
switch (operator) {
case "+": {
return number1+number2;
}
case "-":{
return number1-number2;
}
case "*":{
return number1*number2;
}
case "/":{
if(number2!=0) return number1+number2;
}
default:
//System.out.println("非法运算符:"+operator);
throw new IllegalArgumentException("非法运算符:" + operator);
}
}
}
/*
* 2. 封装,继承,多态
* 使用简单工厂解决多态带来的如何实例化指定类的问题
*/
//父类
abstract class Operation{
abstract double getResult(double number1, double number2);
}
// 加减乘除类
class OperationAdd extends Operation{
public double getResult(double number1, double number2) {
return number1+number2;
}
}
class OperationSub extends Operation{
public double getResult(double number1, double number2) {
return number1-number2;
}
}
class OperationMul extends Operation{
public double getResult(double number1, double number2) {
return number1*number2;
}
}
class OperationDiv extends Operation{
public double getResult(double number1, double number2) {
if (number2==0) {
return 0;
}
return number1/number2;
}
}
//简单工厂类,判断实例化哪一个子类
class OperationFactory{
static Operation getOperation(String operator) {
switch (operator) {
case "+": {
return new OperationAdd();
}
case "-": {
return new OperationSub();
}
case "*": {
return new OperationMul();
}
case "/": {
return new OperationDiv();
}
default:
System.out.println("非法运算符:"+operator);
throw new IllegalArgumentException("非法运算符: " + operator);
}
}
}
工厂类解耦代码,使得增加和修改功能变得方便。但是客户端调用的时候需要额外再调用一次工厂类,调用工厂类实质上替换了new Operation()这样的语句。
《大话设计模式》java实现:第一章-简单工厂模式的更多相关文章
- 第一章 简单工厂模式 及 UML中类图的表示方法
写一个简单计算器程序时,可以写一个操作类,然后加.减.乘.除操作分别继承它,复写操作计算结果的方法.写一个简单工厂类,通过输入的操作符,使用操作类来new一个相应的操作类的子类对象.这样,工厂就实例化 ...
- 设计模式之第2章-抽象工厂模式(Java实现)
设计模式之第2章-抽象工厂模式(Java实现) “上次是我的不对,贿赂作者让我先讲来着,不过老婆大人大人有大量,不与我计较,这次还让我先把上次未讲完的应用场景部分给补充上去,有妻如此,夫复何求.”(说 ...
- 第2章 简单工厂模式(Sample Factory)
原文 第2章 简单工厂模式(Sample Factory) 一般用到的场景:对象多次被实例引用,切有可能会发生变化 拿我们的简单三层举例子 先定义dal层 1 2 3 4 5 6 7 8 cl ...
- 大话设计模式C++实现-第1章-简单工厂模式
一.UML图 二.包括的角色 简单工厂模式包括三个角色: (1)工厂类Factory:工厂类是用来制造产品的. 因此,在Factory中有一个用于制造产品的Create函数或者Generate函数之类 ...
- Java 设计模式系列(二)简单工厂模式和工厂方法模式
Java 设计模式系列(二)简单工厂模式和工厂方法模式 实现了创建者和调用者的分离.分为:简单工厂模式.工厂方法模式.抽象工厂模式 简单工厂模式.工厂方法模式都很简单,就不详细介绍了. 一.简单工厂 ...
- 学习设计模式第二十七 - GoF之外简单工厂模式
示例代码来自<深入浅出设计模式>和<大话设计模式> 概述 简单工厂模式又被称为静态工厂模式,属于类的创建型模式.其实质是由一个工厂类根据传入的参量,动态决定应该创建出哪一个产品 ...
- (转)java反射机制及简单工厂模式
第一步,定义一个接口类 package factory.face; /** * 接口,为了保证返回的对象可以统一用 Product接受 * @author Administrator */ publi ...
- Javascript设计模式理论与实战:简单工厂模式
通常我们创建对象最常规的方法就是使用new关键字调用构造函数,这会导致对象之间的依赖性.工厂模式是一种有助于消除类之间依赖性的设计模式,它使用一个方法来决定要实例化哪一个类.本文详细介绍了简单工厂模式 ...
- 设计模式(C#)——02简单工厂模式
推荐阅读: 我的CSDN 我的博客园 QQ群:704621321 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来.通俗来说,你只关心怎么用,不用关心怎么做 ...
- Java实验项目三——简单工厂模式
Program: 请采用采用简单工厂设计模式,为某个汽车销售店设计汽车销售系统,接口car至少有方法print(), 三个汽车类:宝马.奥迪.大众 (属性:品牌,价格),在测试类中根据客户要求购买的汽 ...
随机推荐
- python绘图库matplotlib:刻度线的方向调整, in, out, inout
前文相关: python绘图库matplotlib:画线的标志marker的设置--类型/size/空心/边线颜色及大小/显示marker超出边界部分 由于工作需要经常用matplotlib来绘图,但 ...
- 白鲸调度系统助力国内头部券商打造国产信创化 DataOps 平台
导读 国内某头部券商是国内排名前三的全国性大型综合证券公司.作为证券行业领头羊之一,该券商一直高度重视核心系统的自主可控以及网络信息安全.早些时候,其已经完成了信创化数据库改造和OA系统适配,接下来的 ...
- Sentry 开源版与商业 SaaS 版的区别
您会在官方的文档中找到大量对 sentry 和 getsentry 的引用.两者都是 Django 应用程序,但 sentry 是开源的, getsentry 是闭源的.里面有什么? https:// ...
- 神经网络之卷积篇:详解Padding
详解Padding 为了构建深度神经网络,需要学会使用的一个基本的卷积操作就是padding,让来看看它是如何工作的. 如果用一个3×3的过滤器卷积一个6×6的图像,最后会得到一个4×4的输出,也就是 ...
- 第 358 场周赛 - 力扣(LeetCode)
第 358 场周赛 - 力扣(LeetCode) 2815. 数组中的最大数对和 - 力扣(LeetCode) 双for遍历即可 class Solution { public: int maxSum ...
- 获取Windows个性化中自带的聚焦锁屏
想要保存登录屏幕(锁屏界面)的背景图片,可以通过以下脚本一键获取: @echo off setlocal enabledelayedexpansion :: Windows Spotlight 锁屏图 ...
- java_类方法&对象方法
int new; 类方法 不能写入和访问其中的对象属性 可以直接通过类调用 通过类调用类方法,没有具体的对象, 所以 不可以访问对象属性, 但是可以访问类属性 public static void d ...
- CANopen学习笔记(一)CANopen入门
CANOpen入门 定位:小网络,控制信号的实时通讯 确保实时性采取的措施 ID域:11bit(CAN标准帧格式) 控制报文采用数据最小字节数 采用生产消费模型(数据无需应答) 需要应答时,采用快 ...
- Maven / Gradle 依赖管理
添加外部依赖 向你的 Maven / Gradle 项目添加依赖的过程可分为如下几步: 搜索依赖 搜索你要安装的依赖,比如你需要 MySQL Connector/J,可以在谷歌搜索"MySQ ...
- Mac 使用远程 Ubuntu 机器进行时间备份
设置 SMB 服务 首先在 Ubuntu 中配置 SMB 服务.可以参考 Ubuntu 设置 SMB 服务. 创建 APFS 磁盘映像 我们在 Ubuntu 上创建出的 SMB 共享文件夹可以用来存放 ...