《大话设计模式》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(), 三个汽车类:宝马.奥迪.大众 (属性:品牌,价格),在测试类中根据客户要求购买的汽 ...
随机推荐
- java多线程之-CAS无锁
1.背景 加锁确实能解决线程并发的的问题,但是会造成线程阻塞等待等问题 那么有没有一种方法,既可以线程安全,又不会造成线程阻塞呢? 答案是肯定的......请看如下案例 注意:重要的文字说明,写在了代 ...
- 快速基于 ClickHouse + Grafana 搭建可观测性解决方案 - 分布式链路追踪篇(ClickHouse 官方博客)
引言 在 ClickHouse,我们认为可观测性仅仅是另一个实时分析问题.作为一款高性能的实时分析数据库,ClickHouse 被用于多种场景,包括时间序列数据的实时分析.其应用场景的多样性推动了大量 ...
- docker部署宝塔面板
环境准备: 系统 rocky:9.2 部署流程: 1.安装docker dnf -y install yum-utils yum-config-manager --add-repo http://mi ...
- JavaScript设计模式样例七 —— 原型模式
原型模式(Prototype Pattern) 定义:用于创建重复的对象,同时又能保证性能.目的:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.场景:在运行期建立和删除原型. let ...
- 全网最适合入门的面向对象编程教程:37 Python常用复合数据类型-列表和列表推导式
全网最适合入门的面向对象编程教程:37 Python 常用复合数据类型-列表和列表推导式 摘要: 在 Python 中,列表是一个非常灵活且常用的复合数据类型.它允许存储多个项,这些项可以是任意的数据 ...
- LuCI Themes
Bootstrap Bootstrap Light Bootstrap Light 就是 Bootstrap Bootstrap Dark Material OpenWrt OpenWrt 2020
- 阿里云CTF and 其他
RE复现 login_system 这个函数就是判断username,点进去发现是线性方程,用z3解 from z3 import * s=Solver() a=[0]*16 for i in ran ...
- Unrecognized SSL message, plaintext connection?
报错:Unrecognized SSL message, plaintext connection? 修改:把 requestContext.setScheme(Scheme.HTTPS);修改为 r ...
- 使用Pandas和NumPy实现数据获取
公众号本文地址:https://mp.weixin.qq.com/s/Uc4sUwhjLTpOo85ubj0-QA 以某城市地铁数据为例,通过提取每个站三个月15分钟粒度的上下客量数据,展示Panda ...
- Git Bash OpenSSL – Generate Self Signed Certificate
前言 以前就写过了, 只是写的太乱, 这篇是一个整理版. 以前的文章: Git Bash 创建证书 PowerShell 创建证书 我已经没有用 PowerSheel 做证书了, 所以就不介绍了. 参 ...