设计模式相关:
开闭原则:实现热插拔,提高扩展性。
里氏代换原则:实现抽象的规范,实现子父类互相替换;
依赖倒转原则:针对接口编程,实现开闭原则的基础;
接口隔离原则:降低耦合度,接口单独设计,互相隔离;
迪米特法则,又称不知道原则:功能模块尽量独立;
合成复用原则:尽量使用聚合,组合,而不是继承;
一、工厂模式
-意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
-何时使用:我们明确地计划不同条件下创建不同实例时。
-如何解决:让其子类实现工厂接口,返回的也是一个抽象的产品。
-关键代码:创建过程在其子类执行。
-应用实例: 1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 2、Hibernate 换数据库只需换方言和驱动就可以。
-优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
-缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
-使用场景: 1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。
- 简单工厂类:一个麦当劳店{工厂类},可以生产多种汉堡。{产品抽象类}
工厂方法类:一个麦当劳店,可以生产多种汉堡。一个肯德基店,也可以生产多种汉堡。
抽象工厂类:百胜餐饮集团下有肯德基和百事公司,肯德基生产汉堡,百事公司生成百事可乐。
二、单例模式
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
关键代码:构造函数是私有的。
应用实例:
1、一个班级只有一个班主任。
2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
* 3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。
优点:
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。
缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
使用场景:
1、要求生产唯一序列号。
2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
* 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
三、策略模式
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。(python 自定义方法映射)
应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3、JAVA AWT 中的 LayoutManager。
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
使用场景: 1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。 2、一个系统需要动态地在几种算法中选择一种。 3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
from abc import abstractmethod,ABCMeta# 创建一个接口class Strategy(metaclass=ABCMeta):@abstractmethoddef doOperation(self,inNum1,inNum2):pass# 创建实现接口的实体类class OperationAdd(Strategy):def doOperation(self,inNum1,inMum2):return inNum1 + inMum2class OperationSubtract(Strategy):def doOperation(self,inNum1,inNum2):return inNum1 - inNum2class OperationMultiply(Strategy):def doOperation(self,inNum1,inNum2):return inNum1*inNum2# 创建Context类class Context():_strategy = Nonedef __init__(self,inStrategy):self._strategy = inStrategydef executeStrategy(self,inNum1,inNum2):return self._strategy.doOperation(inNum1,inNum2)# 调用输出if __name__ == '__main__':aContext = Context(OperationAdd())print("10 + 5 = {0}".format(aContext.executeStrategy(10,5)))aContext = Context(OperationSubtract())print("10 - 5 = {0}".format(aContext.executeStrategy(10, 5)))aContext = Context(OperationMultiply())print("10 * 5 = {0}".format(aContext.executeStrategy(10, 5)))
四、MVC模式
from abc import abstractmethod,ABCMeta# 创建Student类,一个Model类class Student():_rollNo = ""_name = ""def getRollNo(self):return self._rollNodef setRollNo(self,inRollNo):self._rollNo = inRollNodef getName(self):return self._namedef setName(self,inName):self._name = inName# 创建视图StudentViewclass StudentView():def printStudentDetails(self,inStudentName,inStudentRollNo):print("Student :")print("Name : {0}".format(inStudentName))print("Roll No : {0}".format(inStudentRollNo))# 创建控制器class StudentController():def __init__(self,inModel,inView):self._model = inModelself._view = inViewdef setStudentName(self,inName):self._model.setName(inName)def setStudentRollNo(self,inRollNo):self._model.setRollNo(inRollNo)def getStudentRollNo(self):return model.getRollNo()def updateView(self):self._view.printStudentDetails(self._model.getName(),self._model.getRollNo())# 调用输出if __name__ == '__main__':def retrieveStudentFromDatabase():student = Student()student.setName("Robert")student.setRollNo("10")return studentmodel = retrieveStudentFromDatabase()view = StudentView()controller = StudentController(model,view)controller.updateView()# 更新模型数据controller.setStudentName("John")controller.updateView()
