首页 >简历模版 > 内容

《大话设计模式》学习笔记:

2023年10月3日 21:27

一、简单工厂模式
v0.1 写一个计算器:
  输入:a
  输入:b
  输入:operation(四则运算符号)
  if operation then:

    print...

  else

    print..
v0.2 命名有问题,if,else判断太多,除法没有除数等于0的情况
  输入:stra
  输入:strb
  输入:operation
  switch()
  case: ..
  case: ..
  case: if==0 then
v0.3 利用面向对象的特性,显示和计算分离
class view():
  input: stra,strb,operation
  result = Operate.getResult(stra,strb,operation)
  print:result
class Operate():
  @staticmethod
  getResult(stra,strb,operation):
    switch operation:
    case ..
    case ..
v0.4 要增加其他运算,需要连之前的一起编译,修改人员一个马虎可能改到别的东西
class view():
  ...
  result = Operate(stra,strb,???) 这里该如何调用呢?应该由operate符号去判断调用那个类啊,。怎么办?Python里面可以用反射
abstract class Operate:
  double stra,
  double strb,
  double operation
  abstract getResult:
plus extends Operate:
substr extends Operate:
multiply extends Operate:
divide extends Operate:

噹噹噹噹。。。该设计模式大显身手了
简单工厂模式:
class OperationFactory():
  def getInstance(opera)
  switch:opera
  case .. return plusOperation
  case .. return SubOperation
  case .. return MultOperation
  case .. return DivOperation
调用:

Operate o = OperationFactory.getInstance(opera)
result = o(stra,strb,opera)
这样也实现了设计原则中的:开闭原则。要增加运算只需在外面加个类,在工厂中加个case就搞定。

...为什么企鹅跟气候是关联关系?
企鹅要长途跋涉,需要“知道”气候的变化,当一个类“知道”另一个类时,可以用关联。

工厂方法模式:

简单工厂:创建一个工厂,工厂里的方法根据参数不同返回不同的实例,该实例都是某个抽象类的实现。
用抽象类的引用去指向该抽象类的实现
简单工厂:
class SimpleFactory:
  def GetInstance(str):
    case '+':return new Add()
    case '-':return new Substract()
    case '*':return new multiply()
    case '/':return new divide()
Interface IOperation:
  def GetResult(a,b):
class Add(IOperation):
  def GetResult..
class Substract(IOperation):
  def GetResult..
class Multiply(IOperation):
  def GetResult..
clas Divide(IOperation):
  def GetResult..
客户端
IOperation o = SimpleFactory.GetInstance('+')
result = o.GetResult(1,2)
print(result)
(如果要加新运算,需要加case判断,需要加一个新的运算类实现运算接口)

工厂方法模式:薛雷锋同学做好事不留名,薛雷锋住院了 ,你们代替他做好事就是典型的工厂模式的应用
Interface IFactory:工厂接口
def GetInstance:
class AddFactory(IFactory):加法工厂
def GetInstance:
return new Add():
class SubFactory(IFactory):减法工厂
def GetInstance:
return new Sub():
class MultiFactory(IFactory):乘法工厂
def GetInstance:
return new Multi():
class DiviFactory(IFactory):除法工厂
def GetInstance:
return new Divi():
客户端
IFactory addf = new AddFactory()
IOperation add = addf.GetInstance()
result = add.GetResult(1,2)
(如果要加新运算,需要加一个运算工厂,去返回实现运算接口的运算实例)

简单工厂的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖
一个简单工厂模式的工厂类,变成了一个工厂抽象接口和多个具体生成对象的工厂,要增加新运算,就不需要去改内部代码,只需要增加工厂类的实现,和具体的运算类就可以了
这样实现了开闭原则
但是,客户端需要决定用哪个工厂类去实现运算类,选择判断的问题依然存在。
工厂模式把选择判断放到客户端了,而简单工厂是在工厂类里面进行

class LeiFeng:
  def Wash:
  def Cook:
  def Buy:
class XueLeiFeng(LeiFeng):
  def Wash:
  def Cood:
  def Buy:
class Volunteer(LeiFeng):
  def Wash:
  def Cook:
  def Buy:
--------简单工厂: -----
class SimpleLeifengFactory:
  def getLeifengInstance(str):
  case str: return new ...
简单工厂客户端:
LeiFeng a = SimpleLeifengFactory.getLeifengInstance('学雷锋大学生')
LeiFeng b = SimpleLeifengFactory.getLeifengInstance('学雷锋大学生')
LeiFeng c = SimpleLeifengFactory.getLeifengInstance('学雷锋大学生')
a.Wash()
b.Cook()
c.Buy()
写了三次
--------------------------
工厂方法
Interface AbstractFactory:
  def getLeifengInstance:
class StudentLeifengFactory(AbstractFactory):
  def getLeifengInstance:
    return new XueLeiFeng()
class VolunteerLeifengFactory(AbstractFactory):
  def getLeifengInstance:
    return new Volunteer()
工厂方法客户端:
AbstractFactory lffactor = VolunteerLeifengFactory()
LeiFeng a = lffactor.getLeifengInstance()
a.Wash()
a.Cook()
a.Buy()
可见,工厂方法把工厂也抽象了。。。

抽象工厂模式:

模型关系映射,访问数据库的时候,需要根据数据库的不同来解耦,让对象依赖于抽象,
之前工厂方法模式写法:
class OprateUser: User产品操作接口
  def Insert(user)
  def get(id)
class SqlOperateUser(OperateUser):
  def Insert(user): sqlserver实现
  def get(id): SQLserver实现
class AccessOperateUser(OperateUser):
  def Insert(user): Access实现
  def get(id): Access实现

class OprateDept: dept部门产品操作接口
  def Insert(dept)
  def get(id)
class SqlOperateDept(OperateDept):
  def Insert(dept): sqlserver实现
  def get(id): SQLserver实现
class AccessOperateDept(OperateDept):
  def Insert(dept): Access实现
  def get(id): Access实现

class DbFactory:抽象工厂
  def getOpUserInstance():抽象方法获取operateUser
  def getOpDeptInstance():抽象方法获取operateDept
class SqlserverFactory(DbFactory):sqlserver工厂实现
  def getOpUserInstance():
    return SqlOperateUser()
  def getOpDeptInstance():
    return SqlOperateDept()
class AccessFactory(DbFactory): 具体Access工厂,同SQL工厂


客户端
User u = new User()
Dept d = new Dept()
dboperate = new SQLserverFactory()
dboperate.getopUserInstance().insert(u)

还是有依赖。客户端要创建具体的对象
==============================
去掉上面的抽象工厂,
用简单工厂+反射去替换:
class DataAccess:
static string db=sqlserver用反射动态创建的时候
def getOpUserInstance:return db+'OpUser'()
def getOpDeptInstance:return db+'OpDept'

客户端:
User u = new User()
Dept d = new Dept()
dboperate = DataAccess.getOpUserInstance('sqlserver')
dboperate.insert(u)
op = DataAccess.getOpDeptInstance('sqlserver')
op.insert(d)
这样客户端实现全部解耦

单例模式;
简单的单例模式代码
例如点击按钮产生一个工具箱,没有ftb才产生新的或者ftb关闭才产生新的

class Singleton:
static instance
def private Singleton():
def getInstance():
if instance == null:
instance = new Singleton()
return instance
多线程下的单例:
class Singleton:
static instance
def private Singleton():
def getInstance():
lock(sync):锁
if instance == null:
instance = new Singleton()
return instance
上面效率不高,可以这样
class Singleton:
static instance
def private Singleton():
def getInstance():
if instance == null:
lock(sync):锁
if instance == null:
instance = new Singleton()
return instance
不用让线程每次都加锁,而只是在实例未被创建的时候加锁,同时也保证了多线程安全。双重锁定

建造者模式:

肯德基麦当劳流行,因为流程是固定的,变的可能只是调料的重量,这个流水线没有变。
鱼香肉丝味道不同因为流程不一样,每个人具体实现不一样。依赖了具体的实现,违背了依赖反转原则
造小人需求,造瘦人,和胖人,
class thinPerson:
画头
画身体
画手
画脚
class fatPerson:
画头
画身体
画手
画脚
那还想弄高个子,矮个子,会不会出现少画一样东西的局面? 其实,不管是胖子还是瘦子,画的过程是固定的,先头再身体再手再脚,不同的只是每个的大小
这样需要将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示时,可以用建造者模式
建造者模式: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

class Builder: 创建者。决定要创建哪些东西,不分先后
abstract def BuildHead:
abstract def BuildBody:
abstract def BuildHands:
abstract def BuildFoot:

class ThinBuilder(Builder):
实现head
实现body
实现hands
实现foot
class fatBuilder(Builder):
实现head
实现body
实现hands
实现foot
class PersonDirector: 指挥者:决定创建过程
内置Builder
def createPerson:
先画head;
再画body;
再画hands;
再画foot;

客户端:
tp = new ThinBuilder
fp = new FatBuilder
director = new PersonDirector(tp)
director.createPerson 画瘦子
director = new PersonDirector(fp)
director.createPerson画胖子

总结:主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化
建造者模式的好处是建造代码(Builder具体类)与表示代码(Director指挥者类)分离,由于建造者隐藏了该产品是如何组装的,所以
若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了
建造者模式基本代码:
Product产品类),由多个部件组成
Builder抽象建造者类),确定产品由几个部件组成
ConcreteBuilder1具体建造者类1) 每个部件具体实现
ConcreteBuilder2具体建造者类2) 每个部件具体实现
Director指挥者类)决定构建顺序
客户端: 客户不需要知道具体的建造过程
所以说,建造者模式 是在当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时适用的模式

原型模式,
需求,小菜的每份简历,姓名,性别,年龄一样,只是工作经历不一样,为了投不同的公司
v0.1
class Rsume:
name,sex,age,experience
def Rsume(name,sex,age,experience)
def Set...
def Get...

resume1 = Rsume('小菜','男','29','1998-2006 中金公司')
resume2 = Rsume('小菜','男','29','1998-2006 海航公司')

创建二十份简历就要new20次,而且如果我想改年龄,那么每份简历都需要修改。。。
可以用原型模式
v1.0
Interface Cloneable:
def clone:
class Rsume(Cloneable):
name,sex,age,experience
def Rsume(name,sex,age,experience)
def Set...
def Get...
def clone(self):
return copy.copy(self)
客户端————:
R1 = Rsume('小菜','男','29','1998-2006 中金公司')
R2 = R1.clone().setexperience('1998-2006 海航公司')

使用原型模式的好处:每new一次,执行一次构造函数,如果构造函数执行时间长那么就比较低效了。 一般在初始化信息不发生变化的情况下,克隆是最好的办法
这既隐藏了对象创建的细节,又对性能是大大的提高。等于不用重新初始化对象,而是动态地获得对象运行时的状态
注意这个copy.copy方法为浅复制,如果对象里面有可变对象的引用,则只复制可变对象的引用,如果修改了可变对象。如果可变对象变化,那么通过引用去访问就全都变了
如果对象里面有可变对象怎么办呢?
其他语言比较麻烦,需要逐个去浅复制到没有可变对象为止,Python就比较简单了,直接用copy.deepcopy()方法即可

适配器模式: 姚明去NBA打球需要翻译,姚明有进攻防守方法,但是听不懂队友的

class ChinessCenter:
name
def 进攻():
print(进攻)
def 防守():
pring(防守)


class Player:
name
def attack():
def defense():
class Forwards(Player):前锋
def attack():
print("Forward's attack")
def defense():
print("Forward's defense")
class center(Player):中锋
def attack():....
def defense():...
class Guards(Player):后卫
def attack():....
def defense():...

让适配器去适配姚明
class AdaptorCenter(Player):中锋适配器
ChinessCenter yaom = new ChinessCenter()
def attack():
yaom.进攻()
def defense():
yaom.防守()

Player b = new Forwards('巴蒂尔')
b.attack()

Player m = new Forwards('麦克格雷迪')
b.attack()

Player ym = new Forwards('姚明')
ym.attack()
ym.defense()


==new的时候new适配器对象,适配器里面封装了真实的对象,适配器方法封装对象的方法

桥接模式:
手机品牌有m n,
手机软件有游戏,通讯录等,
无论按品牌分类还是按软件分类
手机品牌(派生品牌m 品牌n)(品牌m再派生m游戏 m通讯录 n也是一样)
手机软件(派生游戏,通讯录)(游戏派生m游戏 m通讯录 n也一样)
这样以后维护,无论加手机品牌还是增加软件就变得比较麻烦,要加一大堆的类
像这样分类多的情况,可以把不同的分类给分离。让它们独立变化。互不影响,用桥接模式

手机品牌 品牌m 品牌n 分类1
软件 游戏 通讯录 分类2
handsetBrand
software game maillist

-------
class HandsetBrand:手机品牌抽象类
Software s
def HandsetBrand(s):
def run:
class HandsetM:
def run:
s.run()
class HandsetN:
def run:
s.run()

class Software:软件抽象类
def run:
class Game:
def run:
print('run game')
class Maillist:
def run:
print('run maillist')
客户端-------
Software s = new Game()
HandsetBrand h = new HandsetM(s)
h.run()
..
如果要增加手机品牌或软件,只需要各自增加一个类就行了

装饰器模式
v0.1 自己写的代码,衣服裤子鞋,等不同的穿衣风格,不小心就用了策略+简单工厂模式。如果我想穿两件衣服就不行了。。
class Person:
name
Person(name):
self.name = name
self.Decorator = Decorator

class Decorator: 服饰接口
def clothes():
def trousers():
def shoes():

class fashing(Decorator): 流行服饰
def clothes:...
def trousers:...
def shoes:...
class gentleman(Decorator): 绅士服饰
def clothes:...
def trousers:...
def shoes:...

v0.2 可以穿多件衣服,随便怎么穿:
class Person:
name
def show():
print(name's show)

class Decorator:
def show():
class NormalClothes(Decorator):
def show():普通衣服
class FashionClothes(Decorator):
def show():流行衣服

客户端————:
person = Person()
normal = NormalClothes()
fashing = FashionClothes()
person.show()
normal.show()
fashing.show()

这个相当于众目睽睽之下穿衣服........
建造者模式是稳定的,这个可以随便穿不分先后顺序

component;组件,抽象类,里面有抽象方法
decorator;装饰器类,继承了component类,重写了component里的方法(实际还是调用抽象类的方法)相当于包装了该抽象类。
concreteDecorator;具体装饰器类,继承了装饰器类,重写装饰器类的方法,先运行原装饰器类的方法(即组件接口的方法),再运行该装饰器自己的方法

abstract class Component: 组件抽象类
def Operation():
class ConcreteComponent: 组件抽象的实现
def Operation():
.....
def foo():
...
abstract class Decorator(Component):装饰器抽象类
Component c
def Operation():
c.Operation()
def SetComponent(c):
self.c = c
class ConcreteDecorator1(Decorator):装饰器抽象的实现
str = "d1"
def Operation():
base.Operation()
print(str)
print("装饰器111")
class ConcreteDecorator2(Decorator):
def Operation():
base.operation()
print("装饰器2222")

c = ConcreteComponent()
d1 = ConcreteDecorator1()
d2 = ConcreteDecorator2()

d1.SetComponent(c)
d2.SetComponent(d1)
d2.Operation()

base是调用父类的方法
先运行ConcreteComponent的Operation然后“d1”-“装饰器111”-“装饰器2222”

简单写法
class Component:
def Operation:
pass
class Decorator1(Component):
def Operation:
base.Operation()
print(Decorator1)
class Decorator2(Component):
def Operation:
base.Operation()
print(Decorator2)
是不是跟Python有点像了?????
继承可以理解类中代码的重用,如果类中某块代码要变动可以,把它单独出来放到一个类里面。
把类中的装饰功能从类中搬移去除,这样可以简化原有的类。这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑
尽量保证装饰类之间彼此独立,这样它们就可以以任意的顺序进行组合了

组合模式:
案例: 某集团公司北京总部,有人力资源部,财务部,华东分部属于北京总部,华东分部也有人力资源部,财务部
这种树状组织关系,里面都有重复的人力资源部,财务部,职能都差不多的可以使用组合模式

class Company:
def add:
def del:
def func:

class branch(Company):
string name
List<Company> ls
def add:
def del:
def func:
class leaf(Company):
string name
def add: pass
def del: pass
def func:

客户端————:
branch beijing = new branch('北京') #根节点
leaf hr = new leaf('北京HR部门')
leaf cw = new leaf('北京财务部')
beijing.add(hr)
beijing.add(cw)

branch huadong = new branch('华东分部')
leaf hr = new leaf('华东HR部')
leaf cw = new leaf('华东财务部')
huadong.add(hr)
huadong.add(cw)

beijing.add(huadong)

当发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用
组合结构中所有对象时,就应该考虑用组合模式

享元模式:
外包网站项目,有博客类的 有产品发布类的每个都租用空间很浪费,可以租用一个空间
把核心代码共享,把一些代码不共享。

class User:
name
class Website:抽象网站类
def use(User u):
class ConcreteWebsite(Website):
name
def ConcreteWebsite(String name):
self.name = name
def use(User u):
print(u.name , self.name)
class WebsiteFactory:
Dict c
def WebsiteFactory():
c = new Dict()
def getWebsite(String key):
if c.has(key):
return c(key)
else:
c(key) = new ConcreteWebsite(key)
return c(key)
客户端:
wf = new WebsiteFactory()

u1 = new User('小菜')
website1 = wf.getWebsite('博客')
website1.use(u1)

u2 = new User('大鸟')
website2 = wf.getWebsite('产品展示')
website2.use(u2)

输出:
小菜 博客
大鸟 产品展示

享元对象内部不随环境改变而改变的部分,可共享的 称为享元对象的内部状态,上面的ConcreteWebsite
而随环境改变而改变的,称为外部状态,上面的User
程序设计中,有时需要生成大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数外基本都是
相同的,如果能把那些参数移到类实例外面,在方法调用时将它们传进来,就可以通过共享大幅度减少单个实例的数目

什么情况用享元模式:
如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态

是外部状态 如果删除对象的外部状态,可以用相对较少的共享对象取代很多组对象,也可以考虑用享元模式

代理模式:

卓嫁衣 通过 戴笠 追—— 娇娇 最后戴笠与娇娇在一起了
就是代理
class zuojiayi
def GiveFlower:
def GiveWawa:
def GiveChoclate:

class Proxy:
zuojiayi
jiaojiao
zuojiayi.func(jiaojiao)

==========================修改==================
Interface func:
def GiveDoll:
def GiveFlower:
def GiveChoclate:

class Pursuit(func):追求者知道MM
MM
def GiveDoll(MM)
def GiveFlower(MM)
def GiveChoclate(MM)

class proxy(func):代理包装追求者,代理干的事是包装里的追求者干的
Pursuit
def Proxy(MM)
new Pursuit(MM)
def GiveDoll(MM):
Pursuit.GiveDoll(MM)
def GiveFlower(MM):
Pursuit.GiveFlower(MM)
def GiveChoclate(MM):
Pursuit.GiveChoclate(MM)
class Girl:
name
def Girl(name):
self.name = name
调用:
MM = new Girl('jiaojiao')
proxy = Proxy(MM)

proxy.GiveDoll()
proxy.GiveFlower()
proxy.GiveChoclate()
代理模式就是在访问对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途
应用场景一:远程代理,为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实
应用场景二:虚拟代理,是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。例如很大的HTML网页,图片框通过虚拟代理替代了真实的图片
应用场景三:安全代理,用来控制真实对象访问时的权限。一般用于对象应该有不同的访问权限的时候。
应用场景四:智能指引,是指当调用真实的对象时,代理处理另外一些事。如计算真实对象引用次数,访问一个世纪对象时,检查是否已经锁定它,确保其他对象不能改变它。都是通过代理在访问一个对象时附加一些内务处理

外观模式:
股民炒股,买各种股,各种买各种卖,投资者和股票联系太多。不利于操作,耦合性过高
股民买基金,由基金去投资,股民只关心基金涨还是跌
v0.1原始人
class stock1: def buy ,sell
class stock2: def buy ,sell
class stock3: def buy ,sell
客户端:
s1 = new stock1
s2 = new stock2
s3 = new stock3
s1.buy
s2.buy
s3.buy
s1.sell
s2.sell
s3.sell

v1.0外观模式
class Facade:
stock1
stock2
stock3
def Facade():构造方法
new stock1,
new stock2,
new stock3
def MethodA():
print('组合一')
stock1.buy
stock2.sell
def MethodB():
print('组合二')
stock1.buy
stock2.buy
def MethodC():
print('组合三')
stock1.sell
stock2.sell

客户端:
f = new Facade()
f.MethodA()
f.MethodB()

何时用外观模式??????
首先在设计初期,应该有意识地将不同的两个层分离,比如MVC
其次,开发阶段,子系统往往因为不断的重构演化而变的越来越复杂,用各种模式会产生各种小类,本身是好事但也给外部调用者带来使用上的困难
增加外观facade可以提供一个简单的接口,减少他们之间的依赖。
第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展,但由于它包含非常重要的功能。新需求的开发必须要依赖它
可以为新系统开发一个facade类,让新系统与facade对象交互,facade与遗留代码交互所有复杂工作

观察者模式:
前台mm看见老板报告给里面的同事们,就知道老板回来了
某天前台mm跟老板出去了,跟老板一起回来,同事们偷懒被发现。

class Secretary: 秘书类
内置 List<colleagues> 同事们
内置 string action 前台行动
def add: 添加同事
def notify: 通知同事,遍历同事 co.update
def doaction:mm的行动,老板回来了/老板走了 action=老板回来了
class Colleague:同事
内置 name
内置 秘书mm
def 更新:
mm.action name , 不要偷懒了,快工作~
客户端
mm = new Secretary
co1 = new Colleague
co2 = new Colleague

mm.add(co1)
mm.add(co2)

mm.action()
mm.notify()
可以看出前台类和同事类互相耦合,互相关联。如果前台有事出去就没办法了。。应该让程序依赖抽象,而不是相互依赖
增加观察者类observer
class observer: 抽象观察者
内置 name
内置 Secretary (秘书)
def Observer(name,secretary) 构造方法
abstract def update()
class StockObserver(Observer) 看股票的具体观察者
def StockObserver(): .... 父类构造
def update(): secretary.action name, 关闭股票
class NbaObserver(Observer) 看NBA的具体观察者
def NbaObserver(): ..... 父类构造
def update(): .......关闭NBA
class Secretary; 秘书类
内置 list<colleagues>
内置 string action
def add..
def del..
def notify(): 遍历colleagues, co.update
def doaction(): action='老板来了' return action

比之前好了,,再看看,,秘书类也能抽象出来称为通知者,最后一次老板来了,相当于老板做了通知者

class Subject: 抽象通知者
内置 List<Observer>
内置 String action
def add():
def del():
def doaction():
class Secretary(Subject):

这样,抽象观察者 和 抽象通知者互相关联

观察者模式又叫发布-订阅模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己

.net里面可以进一步降低耦合

Interface Subject:
def notify():

class StockObserver:
内置 name
内置 Subject
def closeStock:
print(subject.action name 关直播)

class NbaObserver:
内置 name
内置 Subject
def closeNBA:
print(subject.action name 关NBA)
class Boss(Subject):
public event EventHandler Update;
def notify():
update()
boss = new Boss()

tongshi1 = new StockObserver('aa',boss)
tongshi2 = new NbaObserver('bb',boss)

boss.Update += new EventHandler(tongshi1.closeStock)
boss.Update += new EventHandler(tongshi2.closeNBA)
boss.action = '老板来了'
boss.notify() 依次将方法当做对象排给event 然后将按顺序执行方法

模板方法模式:
小学的时候,老师把题写黑板上,同学们把题抄下来做,可能会抄错的问题。 实际上每个同学的题都一样,只是答案不一样
v0.1
class TestPaperA: 试卷A
def question1:
print('屠龙刀的材料?a球墨铸铁b马口铁c高速合金钢d碳素纤维')
print('答案b')
def question2:
print('杨过,陆无双铲除无情花造成a沙漠化b稀有物种灭绝c破坏生态d使该植物不再害人')
print('答案d')
def question3:
print('蓝凤凰使华山师徒呕吐不止,开什么药?a阿司匹林b牛黄解毒片c氟哌酸d喝牛奶')
print('答案c')

class TestPaperB:试卷B
def question1:
print('屠龙刀的材料?a球墨铸铁b马口铁c高速合金钢d碳素纤维')
print('答案c')
def question2:
print('杨过,陆无双铲除无情花造成a沙漠化b稀有物种灭绝c破坏生态d使该植物不再害人')
print('答案b')
def question3:
print('蓝凤凰使华山师徒呕吐不止,开什么药?a阿司匹林b牛黄解毒片c氟哌酸d喝牛奶')
print('答案a')
客户端:
a = new TestPaperA
b = new TestPaperB
a.question1
a.question2
a.question3
b.question1
b.question2
b.question3

v1.0
class TestPaper: 试卷抽象类,如果只抽象三个问题,那么客户端还要写答案base.question print('答案a')之类的,可以把答案抽象成一个方法
def question1:
print('屠龙刀的材料?a球墨铸铁b马口铁c高速合金钢d碳素纤维')
print(答案:answer1)
def question2:
print('杨过,陆无双铲除无情花造成a沙漠化b稀有物种灭绝c破坏生态d使该植物不再害人')
print(答案:answer2)
def question3:
print('蓝凤凰使华山师徒呕吐不止,开什么药?a阿司匹林b牛黄解毒片c氟哌酸d喝牛奶')
print(答案:answer3)
def abstract answer1:
def abstract answer2:
def abstract answer3:
class TestPaperA(TestPaper):
def answer1:
return 'a'
def answer2:
return 'b'
def answer3:
return 'b'
这就是模板方法模式
当要完成在某一细节层次一致的一个过程或一系列步骤,
但其个别步骤在更详细层次上的实现可能不同时,我们通常考虑用模板方法模式来处理
推广开来:
abstract class AbstractClass:
def abstract PrimitiveOperation1:
def abstract PrimitiveOperation2:
def TemplateMethod():
PrimitiveOperation1()
PrimitiveOperation2()
print('complete..')
class ConcreteClass1(AbstractClass): 具体类1的operation实现
def abstract PrimitiveOperation1:
print(111111)
def abstract PrimitiveOperation2:
print(22222222222)
class ConcreteClass2(AbstractClass): 具体类2的operation实现
def abstract PrimitiveOperation1:
print(aaaaa)
def abstract PrimitiveOperation2:
print(bbbbbb)
都调用模板方法,各自的具体细节实现不一样
当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模板方法模式把这些行为搬移到单一的地方
这样就帮助子类摆脱重复的不变行为的纠缠

命令模式:
把命令的发出者和命令的执行者分开
可以记录日志,撤销命令等
烤羊肉串的例子: 顾客 服务员 厨师

class Invoker:
Command c
def executeCommand:
c.execute()
class Command:接口
def Execute:

class ConcreteCommand:
Receiver r
def Execute:
r.action()
class Receiver
def Action:
print('do something')
Invoker i = Invoker()
Command c = new ConcreteCommand()
Rceiver r = new Receiver()
c.setReceiver(r) 接受者封装到指令中
i.setCommand(c) 指令封装到调用者中
i.executeCommand()
以上是命令模式的基本用法。
扩展到烤羊肉串的例子中
class Waiter:
list<Command> orders
def SetOrder(Command c)
orders.add(c)
def CancelOrder(Command c)
orders.Remove(c)
def Notify():
遍历orders通知

命令模式好处 ; 把请求一个操作的对象与知道怎么执行一个操作的对象分割开
1较容易设计一个命令队列
2在需要的情况下,较容易将命令记入日志
3允许接收请求一方是否要否决请求
4容易实现请求的撤销和重做
5加新的命令类很容易

状态模式:12点前上午,12-13中午吃饭,困了,13-17下午状态不错, 17-加班 21点困了睡觉

初级版:
class Work:
int Hour
bool finish
def write_program:
if Hour<12: 上午状态不错
elif Hour < 13: 吃饭困了
elif Hour < 17: 下午状态不错
........一堆(if else)

不利于扩展,如果加上其他状态,就需要改write_program代码,全部由这一个方法去维护
违背了开闭原则,使用状态模式
先看最简单的状态模式:
客户端:
work w = new Work()初始化为状态A
w.request()变状态B
w.request()变状态A

class Work:
State s:
def Work():
s = new AState()
def request()
s.handle()
class State:
def handle():
class AState(State):
def handle(Work w):
w.s = new BState()
class BState(State):
def handle(Work w):
w.s = new AState

----------参考上面的例子改写代码---------

class Work:
State s:
int Hour:
bool finish:
def Work():
s = new morningState()
def request()
s.handle()

class State:抽象类
def handle():
class morningState(State):
def handle(Work w):
if w.Hour < 12:
上午状态不错
else
w.s = new noonState()
w.request()
class noonState(State):
def handle(Work w):
if w.Hour < 13:
饿了,困
else
w.s = new AfternoonState()
w.request()
class AfternoonState(State):
def handle(Work w):
if w.Hour < 17
下午状态不错
else
w.s = new NightState()
w.request()
class NightState(State):
def handle(Work w):
if w.Hour < 21
if w.finish:
下班回家,休息
else:
加班,不爽
else
不行了,睡着了

如此,就实现了if else的分离

职责链模式:

小菜加薪,报经理,经理没权限,报人力资源,HR没权限,报总经理
一个职责链

这个是状态模式吗???????
class Context:
int request
Handler hd = new ConcreteHandler1()
def request():
hd.handle(this)

class Handler:
def abstract handle(Context c):

class ConcreteHandler1(Handler):
def handle(Context c):
if c.request>10 and c.request<20:
print("Handler1处理了10-20的情况")
elif c.hd != null:
h = new ConcreteHandler2
c.setHandler(h)
c.request()
class ConcreteHandler2(Handler):
def handle(Context c):
if c.request>=20 and c.request<40:
print("Handler2处理了20-40的情况")
elif c.hd != null:
h = new ConcreteHandler3()
c.setHandler(h)
c.request()
class ConcreteHandler3(Handler):
def handle(Context c):
if c.request>=40:
print("Handler2处理了20-40的情况")

客户端:
Context c = new Context()
c.request()
传递顺序: Handler1-->Handler2-->Handler3

职责链: a handler1 -- b handler2 -- c handler3
class Handler:
Handler successor
def abstract handle(int request):

class ConcreteHandler1(Handler):
def handle(int request):
if request >=10 and request <=20:
print('ConcreteHandler1 .....')
elif successor != null:
successor.handle()

class ConcreteHandler2(Handler):
def handle(int request):
if request > 20 and request <= 40:
print('ConcreteHandler2....')
elif successor != null:
successor.handle()

class ConcreteHandler3(Handler):
def handle(int request):
if request > 40 and request <= 60:
print('ConcreteHandler3 .....')
elif successor != null:
successor.handle()
客户端:
Handler a = new ConcreteHandler1()
Handler b = new ConcreteHandler2()
Handler c = new ConcreteHandler3()
a.setSuccessor(b)
b.setSuccessor(c)

a.handle(70)

再重构加薪的代码就很简单了:

#抽象管理者
class Manager:
Manager m
def handleRequest(Request r):
#经理
class CommonManager(Manager):
def handleRequest(Request r):
if r = '请假1天':
print('批准')
elif r != null:
m.handleRequest()

#总监
class Majordomo(Manager):
def handleRequest(Request r):
if r = '请假3天':
print('批准')
elif r != null:
m.handleRequest()

#总经理
class GeneralManager(Manager):
def handleRequest(Request r):
if r = '请假10天':
print('批准')
elif r != null:
m.handleRequest()

class Request:
String type 请假/加薪/....
int count

客户端:
Manager jingli = new CommonManager()
Manager zongjian = new Majordomo()
Manager CEO = new GeneralManager()
jingli.setManager(zongjian)
zongjian.setManager(CEO)

Request qingjia = new Request('5天')
jingli.handleRequest(qingjia)

解释器模式:

类似于正则表达式, 符合一定的规则(这个规则是定义好的)例如 . + ? 等
然后用一个解释器根据这个规则,解释正则表达式,解释执行
例子:O 1 低音 O 2 中音 O 3 高音 音阶(scale)
CDEFGAB 分别为 1234567 (do re mi fa so la xi) 音符(note)
O 2 E 0.5 G 0.5 A 3 O 3 C 1 O 2 A 0.5 G 1 C 0.5
解释为:中音 3 5 6 高音 1 中音 6 5 1

class PlayText:
String text
def PlayText(String text):
text = self.text
class Expression:
def interpret(PlayText t):
if(t.text.length == 0):
return
else:
playkey = t.text.substring(0,1) key为O (O 2 E ...)
t.text = t.text.substring(2) 截取 (2 E ...)
playvalue = t.text.substring(0,t.text.indexof(' ')) 第一个到第一个空格中间的 这里为2
t.text = t.text.substring(t.text.indexof(' ')+1) 截取 (E ...)
excute(playkey, playvalue)
def excute(String key ,String value):
class Scale(Expression):
def excute(String key, String value):
if key == 'O':
if value = '1':
print('低音')
elif value = '2':
print('高音')
elif value = '3':
print('高音')

class Note(Expression):
def excute(String key, String value):
if key == 'C':
print('1')
elif key == 'D':
print('2')
elif key == 'E':
print('3')
elif key == 'F':
print('4')
elif key == 'G':
print('5')
elif key == 'A':
print('6')
elif key == 'B':
print('7')
客户端:
PlayText pt = new PlayText()
pt.text = 'O 2 E 0.5 G 0.5 A 3 O 3 C 1 O 2 A 0.5 G 1 C 0.5'
Expression e = null
while(pt.text.length > 0):
if pt.text.substring(0,1) == 'O':
e = new Scale()
elif pt.text.substring(0,1) == 'C' | 'D' | 'E' | 'F' | 'G' | 'A' | 'B':
e = new Note()
e.interpret(pt)
如果要增加一个音速
直接增加一个Speed类,然后在客户端条件判断里面加一个分支
可以用简单工厂加反射这样可以不用增加客户端代码了。

中介者模式:
案例 新同事入职,领电脑。去找IT部的某个员工,如果某员工有事就不行了,而如果找IT部经理就由他安排人
就例如两个类直接通信,如果有十几个类,他们之间的关联就很复杂。不符合迪米特法则
可以找个中介者,每个类只需要知道中介者即可。而中介者需要知道他们每个类。这样类之间的通信可以通过中介者,降低复杂性
自己尝试一下:

class Midiater: 抽象中介者,抽象的发送信息方法
def abstract send(String message, Colleague c, Colleague c1)
#c为发送者,如果没有c1.。因为具体中介者的判断是:c为c1就让c2收到,c为c2就让c1收到,但是也应该有接收者啊,万一有c3呢???可以改进一下。
#c为发送者,c1为接收者
class Colleague:抽象同事类,知道中介者
Midiater m
def send(message, Colleague):
def received(message, Colleague):

class ConcreteMidiater(Midiater):具体中介者,知道所有的具体同事类
ConcreteColleague1 c1
ConcreteColleague2 c2
def send(String message, Colleague c, Colleague c1):c为发送者,c1为接收者
if c != c1: 不能自己给自己发信息
c1.received(message, c) 接收者收到发送者c的信息

class ConcreteColleague1(Colleague):
def send(message, Colleague):
m.send(message, this, Colleague)
def received(message, Colleague):
print('收到来自{0}的信息', Colleague)
class ConcreteColleague2(Colleague):
def send(message, Colleague):
m.send(message, this, Colleague)
def received(message, Colleague):
print('收到来自{0}的信息', Colleague)

客户端调用

Mediater m = new ConcreteMediater()
Colleague c1 = new ConcreteColleague1(m)
Colleague c2 = new ConcreteColleague2(m)

c1.setMediater(m)
c2.setMediater(m)

c1.send('你好,c2', c2)
c2.send('hello c1', c1)

中介者与同事类要互相关联
中介者模式很容易在系统中应用,也很容易在系统中误用,当系统中出现了‘多对多’交互复杂的对象群时,不要急于使用中介者模式,
而要先反思你的系统在设计上是否合理
中介者模式优点:
mediater的出现减少了各个Colleague的耦合,使得可以独立改变和复用各个Colleague类和mediater
其次由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来
也就是站在一个更宏观的角度看待系统
中介者模式缺点:
由于ConcreteMediater控制了集中化,于是就把交互复杂性变为了中介者的复杂性,这样就使得中介者会变得比任何一个ConcreteColleague都复杂。

应用场景:中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合 以及想定制一个分布在多个类中的行为,而又不想生成太多的子类的场合

访问者模式:
...
男人成功时,背后多半有一个伟大的女人。
女人成功时,背后大多有一个不成功的男人。
男人失败时,闷头喝酒,谁也不用劝。
女人失败时,眼泪汪汪,谁也劝不了。
男人恋爱时,凡事不懂也要装懂。
女人恋爱时,遇事懂也装作不懂。
男人结婚时,感慨道:恋爱游戏终结时,‘有妻徒刑’遥无期。
女人结婚时,欣慰曰:爱情长跑路漫漫,婚姻保险保平安。
...
小菜代码版本
class Person:
action
def getConclusion:
class Man(Person):
action
def getConclusion():
if action=='成功'
print('{0}{1},背后多半有一个伟大的女人。'.format(this.Class.name,action))
elif action=='失败'
print('{0}{1},闷头喝酒,谁也不用劝。'.format(this.Class.name,action))
elif action=='恋爱'
print('{0}{1},凡事不懂也要装懂。'.format(this.Class.name,action))
class Woman(Person):
action
def getConclusion():
if action=='成功'
print('{0}{1},背后大多有一个不成功的男人。'.format(this.Class.name,action))
elif action=='失败'
print('{0}{1},眼泪汪汪,谁也劝不了。'.format(this.Class.name,action))
elif action=='恋爱'
print('{0}{1},遇事懂也装作不懂。'.format(this.Class.name,action))

客户端:
List<Person> persons = new List<Person>()

man1 = new Man()
man1.action = '成功'
persons.add(man1)

woman1 = new Woman()
woman1.action = '成功'
persons.add(woman1)

...
for p in persons:
p.getConclusion()

如果要增加一个结婚的状态,就需要在Man类和Woman类中各加一个判断分支了,用访问者模式:
一个结论是由两个类来决定:1.男人还是女人 2.状态,成功,失败,恋爱等
这里男人和女人类是不会发生变化的。而状态可能会变化

class Action:
def get_man_conclusion(Man m)
def get_woman_conclusion(Woman w)
class Success(Action):
def get_man_conclusion(Man m)
print('{0}{1},背后多半有一个伟大的女人。'.format(m.Class.name,action))
def get_woman_conclusion(Woman w)
print('{0}{1},背后大多有一个不成功的男人。'.format(w.Class.name,action))
class Falure(Action):

class amativeness(Action):

class Person:
def accept(Action a):
class Man(Person):
def accept(Action a):
a.get_man_conclusion(self)
class Woman(Person):
def accept(Action a):
a.get_woman_conclusion(self)

class ObjectStructure():
List<Person> persons = new List<Person>()
#增加
def add_person(Person p)
persons.add(p)
#删除
def remove_person(Person p)
persons.remove(p)
#遍历
def display(Action a)
for p in persons:
p.accept(a)
客户端:

persons = new ObjectStructure()
persons.add_person(new Man())
persons.add_person(new Woman())


s = new Success()
persons.display(s)

f = new Falure()
persons.display(f)

这样如果要增加结婚状态就很方便了
男女对比这么多的原因是因为人类在性别上就只有男人和女人两类,这也正是访问者模式可以实施的前提
(保证了Action类中的方法数量稳定)
访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化
访问者模式的目的是要把处理从数据结构分离出来,很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于
变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易
反之,如果这样的系统数据结构对象易于变化,经常要有新的数据对象增加进来 ,就不适合使用访问者模式

优点: 增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者,访问者模式将有关的行为集中到一个访问者对象中
缺点: 使增加新的数据结构变得困难

策略模式
去商场购物,根据各种商品单价数量计算总价。
v0.1 输入:count_1,price_1,再输入count_2,price_2再输入....
class Calculate
total = 0
p = count_1 * price_1
total += p
v0.2 我想要打折0.8,0.5..折
if z = "八折"
p = count_1 * price_1 * 0.8
elif z = "五折"
p = count_1 * price_1 * 0.5
......
v0.3 又特么开始不停if.else了,这场景似曾相识。。好像可以用工厂,再加上一个满300返100
调用:Calculate c = DiscountFactory.getInstance(discount) 多态
total = c(ex_total)
class DiscoutFactory(discount):打折对象工厂,根据几折返回不同对象
def getInstance(discount):
switch discount
case "八折" return EightCalculate()
case "五折" return FiveCaculate()
case "满300返100" return Man300Fan100Calculate()
Interface Calculate: 通过原价进行打折的促销接口有一个抽象方法
getRealPay(ex_total):
class EightCalculate implement Calculate:打八折的接口具体实现
getRealPay(ex_total):
return ex_total * 0.8
class FiveCalculate implement Calculate:打五折的接口具体实现
getRealPay(ex_total):
return ex_total * 0.5
class Man300Fan100Calculate implement Calculate:
getRealPay(ex_total):
return ex_total - ex_total // 300 * 100
策略模式登场:
策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
商场用打折还是返利都是一种算法,用工厂生成算法对象没有错,但算法本身只是一种策略,最重要的是这些算法是随时都可能互相替换的,这就是
变化点,而封装变化点是我们面向对象的一种很重要的思维方式

class Context:
Calculate c #促销接口
Context(c)
self.c = c
def useStrategy(ex_total)
c.getRealPay(ex_total)

客户端:
if "五折":
context = new Context(new FiveCaculate())
elif "八折":
context = new Context(new EightCaculate())
context.useStrategy(ex_total)

客户端又要开始有if..else了,怎么办?????
将简单工厂与策略模式结合使用

class Context:
Calculate c
Context(string) 构造方法
if "五折":
c = new FiveCaculate()
elif "八折":
c = new EightCaculate()
elif "300返100":
c = new Man300Fan100Calculate()
def useStrategy(ex_total)
c.getRealPay(ex_total)

看调用:可以理解为用一个现实类把抽象类包装起来了吗???
c = Context("五折")
c.useStrategy(ex_total)

比较一下两种简单工厂模式:
单纯简单工厂在调用的时候需要让客户端“认识”两个类
而简单工厂和策略结合只需要让客户端“认识”一个类就行了
耦合更加降低,算法的父类都不让客户端认识了

策略模式回顾:
不管是打折还是返利,目的都是一样的,就是对原价进行处理。方法一样,实现不同。
可以定义抽象类封装相同点(方法一样)这样可以用相同的代码调用不同的算法,减少各种算法实现类与使用算法类之间的耦合。
可见,使用多态能够很好的实现程序解耦。再弄一个Context类,负责处理不同的策略实现对象
传某个对象就按某个对象进行处理。
但是这样让客户端判断策略,简单工厂跟策略模式结合之后,就在Context类的构造方法中进行判断了
实现分离。
该例中,策略模式用来封装算法。但在实践中,可以用它来封装几乎任何类型的规则,只要分析不同规则之间的相同点,抽象出
抽象类或接口。然后再基于抽象类或接口进行编程

备忘录模式
玩游戏打boss的时候,需要将游戏状态提前保存进度,失败了好退回来重新打
要将血量,魔法,等级等参数保存

原始写法,用变量保存。不用说是很low的了
适配器模式,模板写法:
三个类,
一个类Memento专门保存备忘录,
一个类Caretaker负责定义备忘录要保存的字段,
业务类Originator有保存备忘录和读取备忘录方法

客户端调用:
Orginator o = new Orginator()
Caretaker ct = Caretaker()存放进度的对象
ct.m = 0.CreateMenmento()保存进度
0.RcoverMenmento(ct.m)恢复进度

class Orginator:有两个参数state1 state2
string state1 = 's1'
string state2 = 's2'
def CreateMenmento():
m = new Memento()
m.state1 = state1
return m
def RecoverMemento(Memento m):
state1 = m.state1
class Memento:只保存state1
string state1
class Caretaker:
Memento m


-----游戏进度客户端:-------

Role lixiaoyao = new Role()
State st1 = new State()
st1.r = lixiaoyao.CreateMemento() 李逍遥角色信息存档
lixiaoyao.RecoverMemento(st1.r) 读取李逍遥角色信息

----------游戏进度服务端---------------
class Role:
int vit
int level
int atk
def CreateMemento():
r = new RoleMemento()
r.vit = vit
r.level = level
return r
def RecoverMemento(State s)
vit = s.vit
level = s.level
class RoleMemento:
int vit
int level
class State:
RoleMemento m
-------------------------------------

1.可以自定义备忘录记录哪些信息,
2.对客户端来说备忘录不可见


迭代器模式:
案例,上车买票:甲、乙、丙、丁、小偷 先后上车
售票员让甲乙丙丁买票 小偷被抓住了 要被弄走的时候售票员让他买完票才能走

一个集合里的对象需要全部进行遍历,而遍历的顺序可能有几种方式时(从大到小,从小到大等)
为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口

迭代器模式的简单写法
两个抽象类Aggregate/Iterator 聚集抽象类(createIterator)、迭代器抽象类(first,next,isend)
两个具体类ConcreteAggregate/ConcreteIterator

客户端:

Aggregate c = ConcreteAggregate()

Iterator i = ConcreteIterator(c)

while !i.isend:
i.next()

-----------------------------------------
class Aggregate:抽象聚集类
def createIterator:

class ConcreteAggregate(Aggregate):具体聚集类
list<object> items
def createIterator:
return new ConcreteIterator(this)
def Count:
return items.count
def this[int index]:(索引器)
return items[index]


class Iterator:抽象迭代器类
def First:
def next:
def isend:
def currentItem:

class ConcreteIterator: 具体迭代器类
int current
ConcreteAggregate a
def ConcreteIterator(Aggregate a):
this.a = a
def First:
return a[0]
def next:
current++
return [current]
def isend:
return current>=a.count? true : false
def currentItem:
return a[current]


迭代器写案例:

客户端, 服务器略
ConcreteAggregate a = new ConcreteAggregate()
a[0] = '甲'
a[1] = '乙'
a[2] = '丙'
a[3] = '丁'
a[4] = '小偷'

Iterator i = new ConcreteIterator(a)
object item = i.First()
while(!i.isend):
print(i.currentItem())
i.next()

转载于:https://www.cnblogs.com/revo/p/7428829.html


郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时候联系我们修改或删除,在此表示感谢。

特别提醒:

1、请用户自行保存原始数据,为确保安全网站使用完即被永久销毁,如何人将无法再次获取。

2、如果上次文件较大或者涉及到复杂运算的数据,可能需要一定的时间,请耐心等待一会。

3、请按照用户协议文明上网,如果发现用户存在恶意行为,包括但不限于发布不合适言论妄图

     获取用户隐私信息等行为,网站将根据掌握的情况对用户进行限制部分行为、永久封号等处罚。

4、如果文件下载失败可能是弹出窗口被浏览器拦截,点击允许弹出即可,一般在网址栏位置设置

5、欢迎将网站推荐给其他人,网站持续更新更多功能敬请期待,收藏网站高效办公不迷路。

      



登录后回复

共有0条评论