什么是设计模式?
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
在软件设计中,模式是一些经过了大量实际项目验证的优秀解决方案。熟悉这些模式的程序员,对某些模式的理解也许形成了条件反射。当合适的场景出现时,他们可以很快地找到某种模式作为解决方案。
工厂模式
工厂模式是用来创建对象的一种最常用的设计模式(创建型)。
我们不暴露创建对象的具体逻辑,而是将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂。
工厂模式根据抽象程度的不同可以分为:简单工厂
,工厂方法
和抽象工厂
。
简单工厂
简单工厂模式
又被称为静态工厂方法模式
。可以根据不同的参数返回
简单工厂模式
专门定义一个类来负责创建其他类的实例,被创建的类通常具有不同类的实例共同的父类。
1.工厂类角色
:本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品
2.抽象产品角色
:一般是具体产品继承的父类或者实现的接口,例如运算类
3.具体产品角色
:工厂类所创建的对象就是此角色的实例,例如乘法类,除法类,加法类,减法类
简单工厂模式优缺点:
优点:简单,只要有一个正确的参数,就可以获取需要的对象
缺点:如果后面需要增加产品,需要修改原代码逻辑。静态工厂方法
不能被继承。
代码示例:
// remi老师的版本
//抽象的产品类
class Product{
init(){
console.log("你想怎么生产")
}
}
//具体的产品
class Hanbao extends Product{
init(){
console.log("生产汉堡")
}
}
class Jitui extends Product{
init(){
console.log("生产鸡腿")
}
}
//工厂
class Factory{
static getProduct(name){
switch (name){
case "Hanbao":
return new Hanbao()
break
case "Jitui":
return new Jitui()
break
default:
throw new Error("没有你想要的")
break
}
}
}
Factory.getProduct("Hanbao").init() //工厂生产汉堡
Factory.getProduct("Jitui").init() //工厂生产鸡腿
复制代码
// 我自己的版本
//抽象的产品类
class Calculation{
toDo(x,y){
console.log(`亲,你算什么东西?这可不是骂人啊`)
}
}
//具体的产品
class Add extends Calculation{
toDo(x,y){
console.log(`我要算加法:${x}+${y}=${x+y}`)
}
}
class Minus extends Calculation{
toDo(x,y){
console.log(`我要算减法:${x}-${y}=${x-y}`)
}
}
class Multiply extends Calculation{
toDo(x,y){
console.log(`我要算乘法:${x}*${y}=${x*y}`)
}
}
class Divide extends Calculation{
toDo(x, y) {
console.log(`我要算除法:${x}/${y}=${x/y}`)
}
}
//工厂
class CalculationFactory{
static getResult(name){
switch (name){
case "+":
return new Add()
break
case "-":
return new Minus()
break
case "*":
return new Multiply()
break
case "/":
return new Divide()
break
default:
throw new Error("请不要难为我游戏机")
break
}
}
}
CalculationFactory.getResult("+").toDo(6,6) // 12
CalculationFactory.getResult("-").toDo(6,6) // 0
CalculationFactory.getResult("*").toDo(6,6) // 36
CalculationFactory.getResult("/").toDo(6,6) // 1
复制代码
工厂方法
工厂方法模式
去掉了简单工厂模式
中工厂方法的静态属性
,使得它可以被子类继承。
这样在简单工厂模式
里集中在工厂方法
上的压力可以由工厂方法模式
里不同的工厂子类
来分担。
1.抽象工厂角色
:工厂方法模式的核心。具体工厂角色必须实现的接口或者必须继承的父类。
2.具体工厂角色
:含有和具体业务逻辑有关的代码。创建对应的具体产品的对象。
3.抽象产品角色
:是具体产品继承的父类或者实现的接口。
4.具体产品角色
:具体工厂角色所创建的对象就是此角色的实例。
工厂方法
是解决工厂不能被继承的问题,要符合开闭原则
(对扩展开放,对修改封闭)。
工厂方法模式优缺点:
优点:符合开闭原则,增加一个产品,只需要添加一个具体的产品类和具体的工厂类,使用者无需关心产品如何去创造
缺点:系统代码比较复杂
代码示例:
// remi老师的版本
//抽象的产品电脑 规则
class Computer{
//功能
code(){
console.log("某某电脑能写代码")
}
}
//具体产品
class Xiaomi extends Computer{
code() {
console.log("小米电脑能写代码")
}
}
class Dell extends Computer{
code() {
console.log("戴尔电脑能写代码")
}
}
//抽象工厂
class ComputerFactory{
createComputer(){
console.log("某某工厂生产某某电脑")
}
}
//具体工厂
class XiaomiFactory extends ComputerFactory{
createComputer() {
console.log("小米工厂生产小米电脑")
return new Xiaomi()
}
}
class DellFactory extends ComputerFactory{
createComputer() {
console.log("戴尔工厂生产戴尔电脑")
return new Dell()
}
}
let xiaomi = new XiaomiFactory() //实例对象小米
xiaomi.createComputer().code() //实例对象调用方法
let dell = new DellFactory() //实例对象戴尔
dell.createComputer().code() //实例对象调用方法
复制代码
// 我自己的版本
//抽象的产品计算 规则
class Calculation{
//功能
toDo(){
console.log("某某方法能进行数学计算")
}
}
//具体产品
class Add extends Calculation{
toDo(x,y) {
console.log(`能进行加法运算:${x}+${y}=${x+y}`)
}
}
class Minus extends Calculation{
toDo(x,y) {
console.log(`能进行减法运算:${x}-${y}=${x-y}`)
}
}
class Multiply extends Calculation{
toDo(x,y) {
console.log(`能进行乘法运算:${x}*${y}=${x*y}`)
}
}
class Divide extends Calculation{
toDo(x,y) {
console.log(`能进行除法运算:${x}/${y}=${x/y}`)
}
}
//抽象工厂
class CalculationFactory{
createCalculation(){
console.log("某某工厂生产某某运算")
}
}
//具体工厂
class AddFactory extends CalculationFactory{
createCalculation() {
console.log("加法工厂生产加法运算")
return new Add()
}
}
class MinusFactory extends CalculationFactory{
createCalculation() {
console.log("减法工厂生产减法运算")
return new Minus()
}
}
class MultiplyFactory extends CalculationFactory{
createCalculation() {
console.log("乘法工厂生产乘法运算")
return new Multiply()
}
}
class DivideFactory extends CalculationFactory{
createCalculation() {
console.log("除法工厂生产除法运算")
return new Divide()
}
}
let myAdd = new AddFactory() // 实例化对象
myAdd.createCalculation().toDo(6,6) // 实例化对象调用方法
let myMinus = new MinusFactory()
myMinus.createCalculation().toDo(6,6)
let myMultiply = new MultiplyFactory()
myMultiply.createCalculation().toDo(6,6)
let myDivide = new DivideFactory()
myDivide.createCalculation().toDo(6,6)
复制代码
抽象工厂
抽象工厂模式
是工厂方法模式
的泛化版本,工厂方法模式
是一种特殊的工厂模式
。在工厂方法模式
中,一个具体工厂只能生产一种产品,而抽象工厂模式
中,一个具体工厂可以生产多个产品。
1.抽象工厂角色
:工厂方法模式的核心。是具体工厂角色必须实现的接口或者必须继承的父类。
2.具体工厂角色
:含有和具体业务逻辑有关的代码。创建对应的具体产品的对象。
3.抽象产品角色
:是具体产品继承的父类或者是实现的接口。
4.具体产品角色
:具体工厂角色所创建的对象就是此类角色的实例。
代码示例:
// remi老师的版本
//抽象产品 电脑
class Computer{
//功能
code(){
//
}
}
//具体产品 电脑
class Xiaomi_c extends Computer{
code(){
console.log("xiaomidiannao")
}
}
class Dell_c extends Computer{
code(){
console.log("delldiannao")
}
}
//抽象产品 手机
class Phone{
//功能
call(){
//
}
}
//具体产品 手机
class Xiaomi_p extends Phone{
call(){
console.log("xiaomishouji")
}
}
class Dell_p extends Phone{
call(){
console.log("dellshouji")
}
}
//抽象工厂
class CPFactory{
//生产电脑的规则
createComputer(){
//
}
//生产手机的规则
createPhone(){
//
}
}
//具体工厂
class XiaomiFactory extends CPFactory{
createComputer() {
console.log("xiaomidiannao")
return new Xiaomi_c()
}
createPhone() {
console.log("xiaomishouji")
return new Xiaomi_p()
}
}
class DellFactory extends CPFactory{
createComputer() {
console.log("delldiannao")
return new Dell_c()
}
createPhone() {
console.log("dellshouji")
return new Dell_p()
}
}
//需要的时候直接实例具体工厂
let xiaomi = new XiaomiFactory()
xiaomi.createComputer().code() //小米工厂调用create电脑方法再调用code方法
xiaomi.createPhone().call() //小米工厂调用create手机方法再调用call方法
复制代码
// 我自己的版本
//抽象产品 游戏
class Game{
//功能
keJin(){console.log("游戏可以氪金")}
}
//具体产品 游戏
class tencentGame extends Game{
keJin(){
console.log("腾讯游戏:氪金前你是我儿子,氪金后你就是我爸爸!")
}
}
class neteaseGame extends Game{
keJin(){
console.log("网易游戏:氪金前你是我孙子,氪金后你勉强算我儿子。")
}
}
//抽象产品 音乐
class Music{
listen(){
console.log("音乐可以听")
}
}
//具体产品 音乐
class qqMusic extends Music{
listen() {
console.log("QQ音乐:听歌吗?绿钻了解一下")
}
}
class wangyiyunMusic extends Music{
listen() {
console.log("网易云:到点了到点了。生不出人,我很抱歉。")
}
}
//抽象工厂
class Factory{
createGame(){
console.log("某某工厂生产某某游戏")
}
createMusic(){
console.log("某某工厂生产某某音乐")
}
}
//具体工厂
class tencentFactory extends Factory{ //鹅厂
createGame() {
console.log("腾讯:该充钱了,爸爸")
return new tencentGame()
}
createMusic() {
console.log("QQ音乐:QQ豪华绿钻了解一下")
return new qqMusic()
}
}
class neteaseFactory extends Factory{ //猪厂
createGame() {
console.log("网易:还不氪金,孙子")
return new neteaseGame()
}
createMusic() {
console.log("网易云:生吃个人,我很抱歉")
return new wangyiyunMusic()
}
}
//鹅厂
let tencent = new tencentFactory() // 实例化具体工厂对象,鹅厂
tencent.createGame().keJin() // 鹅厂调用内部方法,实例化具体产品对象--游戏,游戏调用内部方法
tencent.createMusic().listen() // 鹅厂调用内部方法,实例化具体产品对象--QQ音乐,QQ音乐调用内部方法
//猪厂
let wangyi = new neteaseFactory() // 实例化具体工厂对象,猪厂
wangyi.createGame().keJin() // 猪厂调用内部方法,实例化具体产品对象--游戏,游戏调用内部方法
wangyi.createMusic().listen() // 鹅厂调用内部方法,实例化具体产品对象--网易云,网易云调用内部方法
复制代码