在《大话设计模式》中,示例代码使用C#实现,所以我这里使用Java实现一遍书中的设计模式。

第一章是使用简单工厂实现计算器。

遇到了一个问题:在Operation父类中,我们可以定义两个操作数作为成员变量,在类初始化时直接传参,那么GetResult()函数可以直接调用成员变量返回值,而不需要再次传参。也可以不定义成员变量,而是在调用GetRsult()时再传参。那么该如何选择?

  1. 使用成员变量:需要设置每一个运算子类的初始化函数,并修改工厂类,在工厂类初始化运算类的时候传入两个操作数和运算符。初始化函数这部分都是重复的,且需要额外的空间存储运算符。
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;
}
}
  1. 不使用成员变量:重复的代码会大幅减少,每个运算类只需要定义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实现:第一章-简单工厂模式的更多相关文章

  1. 第一章 简单工厂模式 及 UML中类图的表示方法

    写一个简单计算器程序时,可以写一个操作类,然后加.减.乘.除操作分别继承它,复写操作计算结果的方法.写一个简单工厂类,通过输入的操作符,使用操作类来new一个相应的操作类的子类对象.这样,工厂就实例化 ...

  2. 设计模式之第2章-抽象工厂模式(Java实现)

    设计模式之第2章-抽象工厂模式(Java实现) “上次是我的不对,贿赂作者让我先讲来着,不过老婆大人大人有大量,不与我计较,这次还让我先把上次未讲完的应用场景部分给补充上去,有妻如此,夫复何求.”(说 ...

  3. 第2章 简单工厂模式(Sample Factory)

    原文 第2章 简单工厂模式(Sample Factory) 一般用到的场景:对象多次被实例引用,切有可能会发生变化 拿我们的简单三层举例子 先定义dal层 1 2 3 4 5 6 7 8     cl ...

  4. 大话设计模式C++实现-第1章-简单工厂模式

    一.UML图 二.包括的角色 简单工厂模式包括三个角色: (1)工厂类Factory:工厂类是用来制造产品的. 因此,在Factory中有一个用于制造产品的Create函数或者Generate函数之类 ...

  5. Java 设计模式系列(二)简单工厂模式和工厂方法模式

    Java 设计模式系列(二)简单工厂模式和工厂方法模式 实现了创建者和调用者的分离.分为:简单工厂模式.工厂方法模式.抽象工厂模式 简单工厂模式.工厂方法模式都很简单,就不详细介绍了. 一.简单工厂 ...

  6. 学习设计模式第二十七 - GoF之外简单工厂模式

    示例代码来自<深入浅出设计模式>和<大话设计模式> 概述 简单工厂模式又被称为静态工厂模式,属于类的创建型模式.其实质是由一个工厂类根据传入的参量,动态决定应该创建出哪一个产品 ...

  7. (转)java反射机制及简单工厂模式

    第一步,定义一个接口类 package factory.face; /** * 接口,为了保证返回的对象可以统一用 Product接受 * @author Administrator */ publi ...

  8. Javascript设计模式理论与实战:简单工厂模式

    通常我们创建对象最常规的方法就是使用new关键字调用构造函数,这会导致对象之间的依赖性.工厂模式是一种有助于消除类之间依赖性的设计模式,它使用一个方法来决定要实例化哪一个类.本文详细介绍了简单工厂模式 ...

  9. 设计模式(C#)——02简单工厂模式

    推荐阅读:  我的CSDN  我的博客园  QQ群:704621321       工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来.通俗来说,你只关心怎么用,不用关心怎么做 ...

  10. Java实验项目三——简单工厂模式

    Program: 请采用采用简单工厂设计模式,为某个汽车销售店设计汽车销售系统,接口car至少有方法print(), 三个汽车类:宝马.奥迪.大众 (属性:品牌,价格),在测试类中根据客户要求购买的汽 ...

随机推荐

  1. gym.ObservationWrapper使用时的注意点——reset和step函数可以覆盖observation函数

    记录一个刚学习到的gym使用的点,就是gym.ObservationWrapper使用时的注意点--reset和step函数可以覆盖observation函数. 给出代码: import gym cl ...

  2. springboot项目启动时禁止Redis、数据对象加载

    1.背景 2.实现方式 启动类上添加需要排除的自动装配对象 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, H ...

  3. 三台服务器上离线安装redis哨兵集群,一主二从三哨兵

    三台服务器上离线安装redis哨兵集群,一主二从三哨兵 系统安装好gcc环境,(不然编译redis会报错).依旧不知道怎么离线安装gcc环境的可查看CentOS下离线安装gcc环境,图文详细 下载 点 ...

  4. Tim定时器初始化的方法

    #include "stm32f10x.h" // Device header void TimerInit(void) { RCC_APB1PeriphClockCmd(RCC_ ...

  5. Java异常 小白版

    什么是异常 在程序运行时打断正常程序流程的任何不正常的情况称为错误或异常.异常包括用户造成的异常和 系统造成的异常. 例如:网络连接中断.操作符越界.加载的类找不到 异常产生的原因和分类 1. 异常产 ...

  6. 树莓派CM4(二): UART/IIC/SPI调试

    1. 参考资料 资料汇总页面 https://shumeipai.nxez.com/raspberry-pi-datasheets <bcm2711-peripherals.pdf>,下载 ...

  7. 计算机二级c语言学习总结

    咱就是说,还有一周多久要进行计算机二级考试了,咱开始在b站上找一些视频进行学习.毕竟咱c语言实战经验自认为是完全足够应付计算机二级了,所以,咱现在的学习目标是先把计算机二级的大概知识过一遍,进行查漏补 ...

  8. Ubuntu 设置远程桌面(VNC)

    连接 Xfce 4 远程桌面 下载 Xfce 4 桌面环境: sudo apt install -y xfce4 xfce4-goodies 这里会提示你设置显示管理器,我们设置 gdm3 就好. 安 ...

  9. DPABInet做 Network Contruction时一直报错“函数或变量 'nets_netmats' 无法识别”

    DPABInet模块做 Network Contruction时一直显示报错"函数或变量 'nets_netmats' 无法识别",是因为没有将FSLNets导入路径,所以找不到该 ...

  10. SQL SEVER CDC 启动和关闭 操作说明

    什么是变更数据捕获 (CDC)? 变更数据捕获使用 SQL Server 代理记录表中发生的插入.更新及删除. 因此,它使得可以通过关系格式轻松使用这些数据更改. 将为修改的行捕获将这些更改数据应用到 ...