通过代码示例跟我学GOF 设计模式的设计思想——面向接口编程实现

合集下载

跟我学GOF程序代码编程中的各种设计模式——桥接设计模式

跟我学GOF程序代码编程中的各种设计模式——桥接设计模式

1.1跟我学GOF程序代码编程中的各种设计模式——桥接设计模式1.1.1桥接(Bridge)模式1、桥模式“将抽象部分与它的实现部分分离,使它们都可以独立变化”,这是GoF在《设计模式》艺术中的解释,这里的抽象类的实现,一般是在不同的层次中解决。

抽象和实现各自成为一个对象体系,它们由一个桥连接起来,可以各自发展各自的对象层次,而不必顾虑另一方面。

这就是Bridge模式所提供的思想。

Bridge模式更可以提供在各个不同的实现中动态的进行切换,而不必从新编译程序。

2、桥模式的应用场合在如下情况下可以使用桥接模式:1)不希望在业务和业务软件之间存在固定的绑定关系。

2)希望类的抽象和实现部分可以扩充。

3)修改实现部分对用户不产生影响。

4)复用实现部分,由于实现部分所处的层次较低,因此可以和多种业务模块复用。

3、Java 中的AWT即是使用桥接模式简单来讲,AWT提供对程序员的是对窗体界面系统的抽象,而在内部实现中,针对每一种操作系统,分别有不同实现,这就是同位体(Peer)的概念。

当程序员调用AWT对象时,调用被转发到对象所对应的一个Peer上,在由Peer调用本地对象方法,完成对象的显示。

例如,如果你使用AWT创建了一个Menu类的实例,那么在程序运行时会创建一个菜单同位体的实例,而由创建的同位体的来实际执行菜单的现实和管理。

不同的系统,有不同的同位体实现,Solaris JDK将产生一个Motif菜单的同位体,Windows下的JDK将产生一个Windows的菜单的同位体,等等。

同位体的使用,使得交叉平台窗口工具的开发变得极为迅速,因为同位体的使用可以避免重新实现本地窗口控件中已经包含的方法。

实际上,从设计的角度来看,这是一个抽象和实现分离的过程--AWT是抽象,同位体是实现,抽象和实现各自成为一个对象体系,它们由一个桥连接起来,可以各自发展各自的对象层次,而不必顾虑另一方面。

这就是Bridge模式所提供的思想。

跟我学GOF程序代码编程中的各种设计模式——装饰(Decorator)模式

跟我学GOF程序代码编程中的各种设计模式——装饰(Decorator)模式

1.1跟我学GOF程序代码编程中的各种设计模式——装饰(Decorator)模式1.1.1装饰模式1、装饰模式概述(1)装饰模式是一种处理问题的方式需要说明的是,装饰模式是一种处理问题的方式,装饰模式不等于界面设计,这两个概念不要搞混了。

装饰这个概念好像一个油漆工,在原有的家具上刷上色(增加功能),而原有的家具可能是原来已经就有的旧家具,使用装饰模式就有可能增加它的生命周期。

(2)Decorator定义动态给一个对象添加一些额外的职责,就象在墙上刷油漆。

使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。

Decorator模式可以解决这个问题。

Decorator字面的意思是装饰的意思,在原有的基础上,每添加一个装饰,就可以增加一种功能。

2、意图----为什么使用Decorator模式?(1)常规的实现方式----使用继承来实现功能的拓展我们通常可以使用继承的方式来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必会生成很多子类,从而增加系统的复杂性;同时使用继承实现功能的拓展,那我们必须可预见这些拓展功能------因此,这些功能是编译时就确定了,当然也就是静态的。

(2)使用Decorator模式使用Decorator的理由是这些功能需要由用户动态决定加入的方式和时机,因此Decorator模式提供了一种“即插即用”的方法,在运行期间决定何时增加何种功能。

事实上,上面所要解决的意图可以归结为“在不改变对象的前提下,动态增加它的功能”,也就是说,我们不希望改变原有的类,或者采用创建子类的方式来增加功能,在这种情况下,可以采用装饰模式。

3、Decorator模式的程序结构装饰器结构的一个重要的特点是,它继承于一个抽象类,但它又使用这个抽象类的聚合(即装饰类对象可以包含抽象类对象)。

Decorator确实能够很好的缓解当功能组合过多时子类继承所能够带来的问题。

但是在得到很大的灵活性的同时,Decorator在使用时也表现得较为复杂。

gof 23 种设计模式解析附 c语言

gof 23 种设计模式解析附 c语言

gof 23 种设计模式解析附 c语言在计算机科学中,设计模式(Design Patterns)是一套被反复使用的,多数人知道的,经过分类编目的,代码设计经验的总结。

使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

GoF 23种设计模式是设计模式中最经典和最常用的部分,这些模式主要用于解决特定类型的问题。

下面是这些设计模式的C语言解析:1. 工厂方法模式(Factory Method Pattern)```c#include <stdio.h>// 抽象产品类struct AbstractProduct {void use() {printf("AbstractProduct\n");}};// 具体产品类1struct ConcreteProduct1 : public AbstractProduct { void use() {printf("ConcreteProduct1\n");}};// 具体产品类2struct ConcreteProduct2 : public AbstractProduct { void use() {printf("ConcreteProduct2\n");}};// 抽象工厂类struct AbstractFactory {virtual AbstractProduct* createProduct() = 0; };// 具体工厂类1struct ConcreteFactory1 : public AbstractFactory {AbstractProduct* createProduct() {return new ConcreteProduct1;}};// 具体工厂类2struct ConcreteFactory2 : public AbstractFactory {AbstractProduct* createProduct() {return new ConcreteProduct2;}};int main() {ConcreteFactory1 factory1;ConcreteProduct1* product1 = factory1.createProduct(); product1->use(); // 输出 "ConcreteProduct1"delete product1; // 释放内存factory1.createProduct(); // 空指针异常,因为工厂已不再生产任何产品return 0;}```。

跟我学GOF程序代码编程中的各种设计模式——状态设计模式

跟我学GOF程序代码编程中的各种设计模式——状态设计模式
杨教授大学堂 精心创作的优秀程序员 职业提升必读系列资料
1.1 跟我学 GOF 程序代码编程中的各种设计模式——状态设计模式
1.1.1 状态(State)设计模式
1、State 设计模式 不同的状态对应着不同的行为,或者说每个状态有着相应的行为。
2、何时使用 State 设计模式 State 模式在实际使用中比较多,适合“状态的切换”。因为我们经常会使用 If elseif else
return false; } @Override public boolean doTransferAccount(String sAccountID, String tAccountID, float money) {
return false; } @Override public boolean doWithdrawFromAccount(String accountID, float money) {
State 模式的目标就是简化这类应用的代码,把依赖于状态的逻辑集中到一组类,每一 个类代表一种不同的状态,从而避免 if 语句嵌套过深或过于复杂,转而依赖于多态性来调 用不同的方法。
因为,如果对象的状态信息很关键,对象会拥有一些变量来指示如何根据状态做出相 应的动作。这些变量大量地散布于复杂的多层嵌套 if 语句中,来描述对象如何响应可能出 现的事件。用这种方式建立对象模型的最大缺点在于 if 语句可能变得相当复杂一旦要修改 对象的状态模型,往往有多个方法的许多 if 语句需要调整。 4、是否必须使用 State 模式的应用场合
在实际应用中,类似开关一样的状态切换是很多的,但有时并不是那么明显,取决于 你的经验和对系统的理解深度。
这里要阐述的是“开关切换状态”和“一般的状态判断”是有一些区别的,“一般的状 态判断”也是有 if---elseif 结构。

跟我学GOF程序代码编程中的各种设计模式——原型设计模式

跟我学GOF程序代码编程中的各种设计模式——原型设计模式
杨教授大学堂,版权所有,盗版必究。 2/3 页
杨教授大学堂 精心创作的优秀程序员 职业提升必读系列资料
} public static void main(String[] args) { PrototypeTest prototypetest = new PrototypeTest(); } } (4)执行后的结果
杨教授大 精心创作的优秀程序员 职业提升必读系列资料
} return oneObject; } public void addOneMail(String oneMailAddress){ this.mailList.add(oneMailAddress); } public ArrayList<String> getAllMail(){ return this.mailList; } } (2)子类 package com.px1987.prototype; public class Chinese extends Person { public Chinese() { } public void doPrintInfo() { System.out.println(getAllMail()); } } (3)测试类 package com.px1987.prototype; public class PrototypeTest { public PrototypeTest() { Chinese zhang=new Chinese(); zhang.addOneMail("trainict@"); zhang.doPrintInfo(); Chinese wang=(Chinese)zhang.clonePerson(); wang.addOneMail("webmaster@"); wang.doPrintInfo(); zhang.doPrintInfo();

跟我学GOF程序代码编程中的各种设计模式——模板方法模式

跟我学GOF程序代码编程中的各种设计模式——模板方法模式

如果仅仅因为细节上的不同而要重写整个 SQL 语句的构件过程显然是不划算的,那么 采用什么方法可以复用构件过程呢?我们可以采用模板方法。 2、模板方法模式的基本思路 定义一个操作中的算法骨架,而将一些步骤延伸到子类中去,使得子类可以不改变一 个算法的结构,即可重新定义该算法的某些特定步骤。这里需要复用的使算法的结构,也 就是步骤,而步骤的实现可以在子类中完成。 使用 Java 的抽象类时, 就经常会使用到 Template 模式。 因此 Template 模式使用很普遍, 而且很容易理解和使用。模板设计模式一般是一个抽象类,将部分逻辑以具体方法以及具 体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑; 不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。 3、模板方法模式是实现 OCP 的常用方法 使用 Template Method 模式是满足 OCP (The Open-Closed Principle 开放-封闭原则) 的 最常用方法。OCP 原则的基本思想是软件实体(类,模块,函数等等)应该是可以扩展的,
杨教授大学堂,版权所有,盗版必究。 1/2 页
杨教授大学堂 精心创作的优秀程序员 职业提升必读系列资料
但是不可修改的。 即对于扩展是开放的,模块的行为可以扩展,又要“对于更改是封闭的” , 不允许修改原有的代码。 实现 OCP,就应该采用面向接口编程,而不是面向对象编程。 4、模板方法模式的实现实例 在抽象类中定义模板方法的关键是:在一个非抽象方法中调用调用抽象方法,而这些 抽象方法在子类中具体实现。 public abstract class Benchmark{ public abstract void benchmark(); //希望在子类中完成的功能 public final void repeat (int count) { //自己已经实现的功能 benchmark(); } } public class MethodBenchmark extends Benchmark { public void benchmark() { //实现真正的功能的子类 } } Benchmark baseClass=new MethodBenchmark(); baseClass .repeat(10); 至于这样做的好处,很显然啊,扩展性强。以后 Benchmark 内容变化。我们只要再做 一个继承子类就可以,不必修改其他应用代码。 5、模板方法模式的使用场合 (1)一次性实现一个算法的不变部分,并且将可变的行为留给子类来完成。 (2)各子类公共的行为应该被提取出来并集中到一个公共父类中以避免代码的重复。首先 识别现有代码的不同之处,并且把不同部分分离为新的操作,最后,用一个调用这些新的 操作的模板方法来替换这些不同的代码。 (3)控制子类的扩展。 //另一个子类 //使用其它由子类实现的功能 //该方法为 Template 方法

设计模式精解-GOF23种设计模式解析(VS2012重写实现包含Linux Makefile) 代码和原文档已插入本文档

设计模式精解-GOF23种设计模式解析(VS2012重写实现包含Linux Makefile) 代码和原文档已插入本文档

设计模式笔记(C++)一、创建型Factory:工厂1、定义创建对象的接口,封装了对象的创建2、使得具体化类的工作延迟到了子类中3、Factory模式正如我在相应的文档中分析的是为一类对象提供创建接口或者延迟对象的创建到子类中实现。

AbstractFactory:抽象工厂1、创建一组相关或者相互依赖的对象2、AbstractFactory模式是为创建一组(有多类)相关或者依赖的对象提供创建接口3、AbstractFactory模式通常都是使用Factory模式实现(ConcreateFactroy)Singleton:单例1、Singleton模式保证一个类仅有一个对象,并提供一个访问它的全局访问点。

2、全局变量不能防止实例化多个对象。

3、全局变量将使得对象在无论是否用到都要被创建。

Builder:创建者1、Builder模式的意图是非常容易理解、间接的:将一个复杂对象的构建与它的表示分离,使用同样的构建过程可以创建不同的表示(在示例代码中可以通过传入不同的参数实现这一点)。

Builder模式和AbstractFactory模式在功能上很相似,因为都是创建大的复杂的对象,它们的区别是:Builder模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说Builder模式中对象不是直接返回的。

而在AbstractFactory 模式中对象是直接返回的,AbstractFactory模式强调的是为创建多个相互依赖的对象提供一个同一的接口。

Prototype:原型1、Prototype模式通过复制原型(Prototype)而获得新对象创建的功能,这里Prototype本身就是“对象工厂”(因为能够生产对象),实际上Prototype 模式和Builder模式、AbstractFactory模式都是通过一个类(对象实例)来专门负责对象的创建工作(工厂对象),它们之间的区别是:Builder模式重在复杂对象的一步步创建(并不直接返回对象),AbstractFactory模式重在产生多个相互依赖的对象,而Prototype模式重在从自身复制自己创建新类。

UML-GoF设计模式

UML-GoF设计模式

UML-GoF设计模式我认为,本章是重点中的重点。

并⾮23个模式都被⼴泛应⽤,其中常⽤和最为有效的⼤概有15个模式。

1、适配器(Adapter)1)、使⽤场景使⽤⼀个已经存在的类,但如果他的接⼝,也就是他的⽅法和你的要求不相同时,考虑使⽤是适配器模式。

就是说,双⽅都不修改⾃⼰的代码的时候,可以采⽤适配器模式。

2)、结构图3)、相关模式外观对象:隐藏外部系统的资源适配器也被视为外观对象,因为资源适配器使⽤单⼀对象封装了对⼦系统或系统的访问。

资源适配器:当包装对象时为不同外部接⼝提供适配时,该对象叫资源适配器4)、准则类名后缀为“Adapter”。

5)、⽤到的GRASP原则2、⼯⼚模式1)、使⽤场景该模式也常称为“简单⼯⼚”或“具体⼯⼚”。

如:1)、存在复杂创建逻辑2)、为提⾼内聚⽽分离创建者职责(关注点分离)因此,创建称为⼯⼚的纯虚构对象来处理这些创建职责。

2)、结构⼀般xxxFactory应该是单实例类。

3)、相关模式通常使⽤单例模式来访问⼯⼚模式。

由谁创建⼯⼚呢?⼀般采⽤单例模式。

3、单例模式1)、使⽤场景只有唯⼀实例的类即为“单实例类”。

对象需要全局可见性和单点访问。

因此,建议对类定义静态⽅法⽤以返回单实例。

2)、相关模式单例模式:通常⽤于创建⼯⼚对象和外观对象以上整合例⼦:4、策略模式1)、使⽤场景销售的定价策略(也可叫做规则、政策或算法)具有多样性。

在⼀段时间内,对于所有的销售可能会有10%的折扣,后期可能会对超出200元的销售给予10%的折扣,并且还会存在其他⼤量的变化。

因此,在单独的类中分别定义每种策略/规则/政策/算法,并且使其具有共同接⼝。

2 )、结构策略模式,共同的⽅法内传⼊的参数,通常是上下⽂对象,上图就是sale。

3)、结合⼯⼚模式1)、使⽤⼯⼚模式创建这些策略类2)、使⽤单例模式创建⼯⼚类。

5、组合模式1)、使⽤场景如果有重叠怎么办?⽐如:1)⽼年⼈折扣20%2)购物⾦额满200元享受15%折扣因此,如何能够处理像原⼦对象⼀样,(多态的)处理⼀组对象或具有组合结构的对象呢?答:定义组合和原⼦对象的类,使他们具有相同的接⼝。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

1.1通过代码示例跟我学GOF 设计模式的设计思想——面向接口编程实现1.1.1在数据库连接组件中应用面向接口编程实现1、设计数据库连接组件对外的接口(1)为什么要应用接口?如何实现接口?1)应用接口编程实现的最主要的目的是达到分离“分析设计”和“功能实现”并最终达到有助于“满足变化”的应用目的;2)其次,约束不同的功能实现程序,必须要提供并实现在接口中所提出的各种功能要求;3)有助于团队开发中的模块分工,协作开发——两个模块通过接口互联,其一为接口的使用者,另一个为接口的功能实现者,当然还有接口的制定者(一般为设计师)。

通过这个接口,调用者无须知道目标对象的具体详细信息,只需要知道它实现了这个接口,那么它便可以依据这个接口来使用这个对象了。

接口的实现者按照接口的制定者的设计要求完成相关的功能实现。

因此,接口本质上就是由制定者来协调实现者和调用者之间的关系。

当然,也只有接口的实现者和接口的调用者都遵循“面向接口编程”这个准则后,制定者的协调目的才能达到。

(2)如何实现接口?为了能够实现接口,需要通过相关的功能类实现,并在实现类重写接口中的所有的成员方法。

2、在项目中添加一个数据库连接的接口接口的名称为ConnectDBInterface,包名称为com.px1987.webbank.dao.inter,如下为实现的示图截图:3、设计该接口中的功能方法方法4、ConnectDBInterface接口的代码示例package com.px1987.webbank.dao.inter;import java.sql.Connection;import com.px1987.webbank.exception.*;public interface ConnectDBInterface {public Connection getConnection() throws WebBankException;public void closeDBCon() throws WebBankException;public boolean isDBConnectionClose();}5、为ConnectDBInterface接口添加相关的实现类由于接口本身只是定义了相关的功能方法,并没有给出具体的功能,因此需要为上面的ConnectDBInterface接口提供对应的功能实现类。

在下面的示例中目前先采用“JDBC的直接连接方式”实现相关的数据库连接功能。

希望读者回顾在JDBC中有几种连接的方式?(1)添加ConnectDBInterface接口的实现类类名称为ConnectDBBean,包名称为com.px1987.webbank.dao.imple,如下为实现的示(2)编程该ConnectDBBean实现类的功能代码package com.px1987.webbank.dao.imple;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.util.logging.Level;import java.util.logging.Logger;import com.px1987.webbank.dao.inter.ConnectDBInterface;import com.px1987.webbank.exception.WebBankException;public class ConnectDBBean implements ConnectDBInterface {static String JDBC_DBDriver_ClassName = "com.mysql.jdbc.Driver";String JDBC_DSN_URL = "jdbc:mysql://localhost:3306/webbank";String JDBC_dbUserName="root";String JDBC_dbUserPassWord="root";private java.sql.Connection con = null;private static Logger logger = Logger.getLogger(ConnectDBBean.class.getName());请注意为什么要将此语句放在static语句块中*/static{try{Class.forName(JDBC_DBDriver_ClassName);}catch (ng.ClassNotFoundException e){ //在此先不考虑异常处理logger.log(, "不能正确地加载JDBC驱动程序"+e.getMessage());}}public ConnectDBBean() throws WebBankException {}public void initDBConnection() throws WebBankException{try{con = DriverManager.getConnection(JDBC_DSN_URL,JDBC_dbUserName,JDBC_dbUserPassWord);}catch (java.sql.SQLException e) {logger.log(, e.getMessage());throw new WebBankException("不能正确地连接数据库并且出现SQLException");}catch (NullPointerException e){logger.log(, e.getMessage());throw new WebBankException("不能正确地连接数据库并且出现NullPointerException");}}public void closeDBCon() throws WebBankException {请注意为什么要加此条件判断?*/if(con==null){return;}try {/**注意:要识别是否为重复调用,否则会出现数据库连接已经关闭的状况*/con.close();con = null;}catch (SQLException e){logger.log(, e.getMessage());throw new WebBankException("不能正确地关闭数据库连接");}}public Connection getConnection() throws WebBankException {initDBConnection();return con;}public boolean isDBConnectionClose(){return (con==null)?true:false;}}1.1.2分离数据库连接组件中的与环境有关的参数1、与配置文件相关的一些概念——为什么要采用配置文件?(1)配置文件的主要作用是什么?主要达到灵活地满足变化,比如数据库系统发生改变后,不需要改变相关的数据库连接的功能实现代码,而只需要改变配置文件中的各个配置的工作参数。

因此,利用该配置文件可以封装系统中的各个“可变的工作参数”。

因为这些“可变的工作参数”其实也就是“策略模式”中的“环境”。

(2)是采用*.properties属性文件还是*.xml格式文件?本示例首先选择*.properties属性文件,然后再改变为XML格式的配置文件。

因为属性文件配置文件比较简单,而且对它的解析程序的功能实现也比较简单;但XML配置文件可以定义多层次的复杂数据关系,但解析的程序代码实现比较复杂。

因此,简单的配置数据项目一般都应用属性配置文件,而复杂的数据关系的配置文件则需要应用XML格式的配置文件。

(3)如何实现对属性配置文件中的各个配置项目进行读写?可以利用java.util.Properties类及其中的各个方法,可以参见下面的代码示例。

2、在项目中添加一个属性配置文件(1)该属性配置文件名称为classNameConfig.properties,如下为实现过程中的示图:(2)在该属性配置文件中添加相关的配置项目目前在该属性配置文件中添加的配置项目的内容如下,这些配置项目的数据实现连接MS SQLServer2000的数据库系统。

当然,改变这些配置项目的参数,同样也可以实现连接MySQL数据库、Oracle数据库系统。

本示例在后面将改变为连接MySQL数据库系统。

3、在项目中添加一个获得配置属性项目数据的解析类(1)解析程序类名称为ClassNameConfig类,包名称为com.px1987.webbank.config,该类也就是策略模式中的环境类(Context)。

如下为实现过程中的示图:(2)编程ClassNameConfig程序类的代码package com.px1987.webbank.config;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.Properties;import com.px1987.webbank.exception.WebBankException;public class ClassNameConfig {public ClassNameConfig()throws WebBankException {}/**为什么要将下面的oneProperties定义为静态?*/static Properties oneProperties=null;static{/**请注意这段代码的作用*/oneProperties=new Properties();/**请注意下面的代码示例中的文件路径中的“/”的含义*/InputStream propertiesFileStream=ClassNameConfig.class.getResourceAsStream("/classNameConfig.properti es");try {oneProperties.load(propertiesFileStream);} catch (IOException e) {System.out.println("在加载属性文件时程序出现了异常错误!");}}public static String getProperty (String propertiesName){return oneProperties.getProperty(propertiesName);}public static void setProperty (String propertiesName,String propertiesValue){ oneProperties.put(propertiesName, propertiesValue);}public void savePropertiesItem(String propertiesFileName)throws WebBankException{OutputStream propertiesFileStream=null;try {propertiesFileStream = new FileOutputStream(propertiesFileName);} catch (FileNotFoundException e) {throw new WebBankException("在保存属性文件时程序出现了异常错误!");}try {oneProperties.store(propertiesFileStream, "这是修改后的属性文件内容");} catch (IOException e) {throw new WebBankException("在保存属性文件时程序出现了异常错误!");}}public void savePropertiesItemToXML(String xmlPropertiesFileName)throws WebBankException{OutputStream propertiesFileStream=null;try {propertiesFileStream = new FileOutputStream(xmlPropertiesFileName);} catch (FileNotFoundException e1) {throw new WebBankException("在保存属性文件时程序出现了异常错误!");}try {oneProperties.storeToXML(propertiesFileStream, "这是修改后的属性文件内容","gb2312");} catch (IOException e) {throw new WebBankException("在保存属性文件时程序出现了异常错误!");}}}如下为上面的代码示例的实际屏幕的局部截图。

相关文档
最新文档