golang架构设计开闭原则手写实现
作者:ioly 发布时间:2023-07-21 22:01:36
缘起
最近复习设计模式
拜读谭勇德的<<设计模式就该这样学>>
该书以java语言演绎了常见设计模式
本系列笔记拟采用golang练习之
开闭原则
开闭原则(Open-Closed Principle, OCP)指一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。所谓开闭,也正是对扩展和修改两个行为的一个原则。
实现开闭原则的核心思想就是面向抽象编程。
场景
某线上学习平台, 提供系列课程产品(接口: ICourse)
每个课程有id,name,price等属性
现在平台搞促销, golang课程(GolangCourse)打六折
如何上架打折课程? 是直接修改原golang课程的价格, 还是增加折后golang课程?
思路
开闭原则, 就是尽量避免修改, 改以扩展的方式, 实现系统功能的增加
增加"优惠折扣"接口 - IDiscount
增加"折后golang课程" - DiscountedGolangCourse, 同时实现课程接口和折扣接口
DiscountedGolangCourse继承自GolangCourse, 添加实现折扣接口, 并覆盖ICourse.price()方法
ICourse.go
principles/open_close/ICourse.go
课程接口
package open_close
type ICourse interface {
ID() int
Name() string
Price() float64
}
GolangCourse.go
principles/open_close/GolangCourse.go
golang课程类, 实现ICourse接口
package open_close
type GolangCourse struct {
iID int
sName string
fPrice float64
}
func NewGolangCourse(id int, name string, price float64) ICourse {
return &GolangCourse{
iID: id,
sName: name,
fPrice: price,
}
}
func (me *GolangCourse) ID() int {
return me.iID
}
func (me *GolangCourse) Name() string {
return me.sName
}
func (me *GolangCourse) Price() float64 {
return me.fPrice
}
IDiscount.go
principles/open_close/IDiscount.go
折扣接口
package open_close
type IDiscount interface {
Discount() float64
}
DiscountedGolangCourse.go
principles/open_close/DiscountedGolangCourse.go
该课程同时实现ICourse和IDiscount接口
package open_close
type DiscountedGolangCourse struct {
GolangCourse
fDiscount float64
}
func NewDiscountedGolangCourse(id int, name string, price float64, discount float64) ICourse {
return &DiscountedGolangCourse{
GolangCourse: GolangCourse{
iID: id,
sName: name,
fPrice: price,
},
fDiscount : discount,
}
}
// implements IDiscount.Discount
func (me *DiscountedGolangCourse) Discount() float64 {
return me.fDiscount
}
// overwrite ICourse.Price
func (me *DiscountedGolangCourse) Price() float64 {
return me.fDiscount * me.GolangCourse.Price()
}
open_close_test.go
main/open_close_test.go
课程接口测试用例
package main
import (
"testing"
)
import (ocp "learning/gooop/principles/open_close")
func Test_open_close(t *testing.T) {
fnShowCourse := func(it ocp.ICourse) {
t.Logf("id=%v, name=%v, price=%v\n", it.ID(), it.Name(), it.Price())
}
c1 := ocp.NewGolangCourse(1, "golang课程", 100)
fnShowCourse(c1)
c2 := ocp.NewDiscountedGolangCourse(2, "golang优惠课程", 100, 0.6)
fnShowCourse(c2)
}
测试
$> go test -v main/open_close_test.go
=== RUN Test_open_close
open_close_test.go:10: id=1, name=golang课程, price=100
open_close_test.go:10: id=2, name=golang优惠课程, price=60
--- PASS: Test_open_close (0.00s)
PASS
ok command-line-arguments 0.001s
来源:https://segmentfault.com/a/1190000039148996
猜你喜欢
- 【译者的话】我们曾经在《透视色轮》一文中探讨过色轮的构成及作用,但你可能更多的只是将其作为了解颜色关系的一个工具,却不一定将其作为实际设计中
- 针对border边框属性在浏览器中的渲染方式很早以前就开始在QQ群中看到大家在讨论,而我也一直以border:0 none;的方式处理。其中
- if rs.bof then 表示:当前指针的位置是在第一行记录之前 if rs.eof then 表示:当前指针的位置是在最后一行记录之后
- 今天不小心又点了收藏夹里Google的新首页风格的地址,赫然发现又变了!从这个页面上线以来,偶尔会去看看,短短一年的时间,已经变换了至少三次
- 大家都知道系统存储过程是无法用工具导出的(大家可以试试 >任务>生成SQL脚本) 因为系统存储过程一般是不让开发人员修改的。 需
- 前三篇文章中,明确了栅格系统的设计细节和适用范围。这一篇将集中讨论960栅格系统的技术实现。Blueprint的实现Blueprint是一个
- 主要利用了XMLHTTP的一些方法和属性来获取服务器的信息。 以下是全部源代码: &
- ERROR 2003:Can't connect to MySQL server on 'localhost' (1
- 当我们建立一个数据库时,并且想将分散在各处的不同类型的数据库分类汇总在这个新建的数据库中时,尤其是在进行数据检验、净化和转换时,将会面临很大
- 问:如何在SQL Enterprise Manager version 6.5下操作SQL Server 6.0的服务器?答:在使用SQL
- 本文实例讲述了go语言睡眠排序算法。分享给大家供大家参考。具体分析如下:睡眠排序算法是一个天才程序员发明的,想法很简单,就是针对数组里的不同
- 在这篇asp之数学函数里,我们将会以表格的形式,让大家了解到关于ASP中能用到的数学函数,里面包括一个数的绝对值、一个数的平方根
- 目前网络数据库的应用已经成为最为广泛的应用之一了,并且关于数据库的安全性,性能都是企业最为关心的事情。数据库渐渐成为企业的命脉,优化查询就解
- 前段时间跟这suggest项目走,没想到这么一个小小的输入框居然会带来那么多的问题。首先来比较一下几个主流的搜索引擎的suggest效果。为
- 在官网下载源码包:https://www.php.net/downloads.php步骤:1、解压命令:tar -xjvf php.tar.
- # 建表CREATE TABLE `T_TEST` ( `Id` int(11) NOT NULL AUTO_INCREMENT
- 说明:这个例子,首先是把SPAN里的内容用display:none;干掉,就是不显示; 然后在A:HOVER时,再把SPAN里的内容disp
- --语 句 功 能 --数据操作 SELECT --从数据库表中检索数据行和列 INSERT --向数据库表添加新数据行 DELETE --
- 下面这段代码是asp编写的用来识别客户端是否为手机浏览器,以及手机类型的代码。主要用于手机网站的建设,以便实现相同网址下的不同版本网站(比如
- 我们现在回到函数上。记得我们用 SUM 这个指令来算出所有的 Sales (营业额)吧!如果我们的需求变成是要算出每一间店 (store_n