赞
踩
该文章适用于之前学习过设计模式,但是基本忘了。使用该文章进行快速回忆。因为是应付面试(不是笔试),所以该文结合了自己的理解,使用大白话来解释各个模型,如有错误或不严谨的地方,欢迎在评论区指正。
若之前没有学习过设计模式,可以将该文章死记硬背,然后应付面试。
设计模式详细学习,可以参见 http://c.biancheng.net/view/1317.html
设计模式:软件设计模式是对各种面向对象方法的一种总结。前辈们遇到了好多设计问题,然后利用面向对象解决了。然后他们把解决方案汇总起来,形成了20多种设计模式。它可以有效的帮助我们利用面向对象,来提高代码的复用性、扩展性等。 设计模式包含4个关键元素:
组合:将多个种类的对象组合成一个新的对象。如 显示器 + 键盘 + 鼠标 +主机 = 电脑。
聚合:将多个同种对象聚起来,形成一个新的对象,如 50个学生 = 一个班级
用户:在设计模式中,用户并不是指具体使用系统的用户,而是使用你代码,或者是扩展你代码的其他程序员。
UML主要用于表示类与类之间的关系。例如:
如图,在该图中
该图表示类,其中 Rectangle为类名。 length:double
为 属性:类型
。getArea():double
为 方法:返回值
圆圈代表接口,getArea():double
为该接口的方法
虚线箭头表示实现,用于表示类实现了这个接口。
如果为实线,则为继承。
这个表示依赖。可以简单的理解为左边的类用到了右边的类。
这个是聚合,如果这个菱形为实心的,则为组合。
对扩展开放,对修改关闭。就是如果要修改原有的功能或者是扩展功能,尽量去扩展原有的代码,而不是修改原来已有的代码。
任何子类对象都应该可以替换其派生的超类对象 。即,子类可以扩展父类的功能,但不要修改父类原有的功能。 也就是说,当一个子类继承父类后,尽量不要去重写它原有的方法。
要面向接口编程,不要面向实现编程。两个模块交互时,都访问各自接口,而不是具体的实现类。
一个对象要专注于一种事情,不要让它担任太多责任。
一个接口尽量只包含用户关心的内容。就是一个接口不要太庞大。
如果两个软件实体之间不是特别必要,尽量不要让他们直接通信。而是找个第三方进行转发,比如使用MQ(消息队列)。
如果在“组合/聚合”和“继承”之间做抉择时,优先选择“组合/聚合”。
设计模式分为:
单例模式提供了两种方式:
public static synchronized LazySingleton getInstance() {
//getInstance 方法前加同步
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
private static final HungrySingleton instance = new HungrySingleton();
public static HungrySingleton getInstance() {
return instance;
}
补充,深拷贝的实现方式:
return new Dog()
。在简单工厂中,有一个缺点:如果我们想让工厂再能多生产一种东西,那就要修改这个工厂类的方法。这显然不符合开闭原则。
针对这个问题,所以引出了工厂方法模式。
在简单工厂模式中,不管生产什么品牌的鞋子,都用同一工厂。
而在工厂方法模式中,想要生产某一个品牌的鞋子,就使用其对应的工厂。也就是说一个工厂只生产一种产品,如果你想要的三种不同的产品,你就要有三个工厂。比如,耐克工厂专门生产耐克鞋,阿迪工厂专门生产阿迪鞋。当你后期想要扩展的时候,你就可以再来一个安踏工厂专门生产安踏鞋。
在工厂方法模式中,存在一个缺点,一个工厂只能生产一种产品。如耐克工厂只能生产耐克鞋。但是如果我想让耐克工厂即能生产耐克鞋也可以生产耐克衣服就没办法了。
所以为了解决这个问题,就引出了抽象工厂。在抽象工厂类中定义多个产品,即定义它的子类应该生产哪些产品。 这样就可以做到,耐克厂可以生产耐克鞋和耐克衣服,阿迪工厂可以生产阿迪鞋和阿迪衣服。
但是很明显有一个缺点:如果抽象工厂再加一种产品,比如帽子,那么所有的具体工厂类都要改造。
Computer computer=new Computer.Builder("因特尔","三星")
.setDisplay("三星24寸")
.setKeyboard("罗技")
.setUsbCount(2)
.build();
代理模式的实现方式:
@Autowired
private IService service;
你在写代码时,你并没有实例化这个service
。而是将该实例通过spring进行注入,这样spring在就可以在运行时,根据你配置的规则,来决定这个service
应该使用正常的bean还是使用其代理类。
装饰器的典型应用:
BufferedReader in = new BufferedReader(new FileReader("filename.txt"));
String s = in.readLine();
装饰器模式为FileReader增加了Buffer功能。
共同点:
区别:
主要角色解释:
在该图中,选定Bag的类型作为主属性,通过继承的方式定义不同的Bag。而包的颜色作为次要属性,通过组合的方式进行实现。
扩展:
这个模式有一个缺点,如果要增加子系统,或者变更外观角色,那么就要修改源代码,不符合开闭原则。 解决方案也很简单,只需要对外观角色提供抽象即可。
将外观对象提供一个抽象类。客户在使用时,使用其抽象类,这样在变更子系统后,可以重新创建一个具体外观类。
扩展:
共同点:它们都适用于,如果两个元素改动比较小的话,可以使用该模式。
区别:
其实这种模式大家应该基本天天在用,就是对象里面套对象。只不过可能不知道这也是一种设计模式而已。
用通俗的语言解释一下观察者模式:
public void relay(Colleague cl) {
for (Colleague ob : colleagues) {
if (!ob.equals(cl)) {
((Colleague) ob).receive();
}
}
}
public void send() {
System.out.println("具体同事类1发出请求。");
mediator.relay(this); //请中介者转发
}
相同点:中介者模式和观察者模式都可以用于当一方状态发生变化时通知其他人。
区别:
策略模式其实到处都是,一个接口有好几个实现类,你选择其中一个进行使用。
但有一点不同的是,策略模式需要有策略的选择角色,比如环境类。通过设置环境对象,让环境对象帮助用户选择使用哪一种策略,而不是由用户自己选择。
策略模式也可以和工厂模式结合使用,使用工厂来决定应该生产出哪一种策略来让用户使用。
while(obj.hasNext()) {
obj.next();
}
扩展:
平时用的 for-each 的本质就是迭代器模式。例如下列代码:
public class Test implements Iterable {
public Iterator iterator() {
return null;
}
public static void main(String[] args) {
Test test = new Test();
for (Object o : test) {
System.out.println(o);
}
}
}
该代码是可以编译通过的,因为Test类实现了Iterable
方法,所以可以使用for-each遍历它。否则,则编译会报错。
访问者模式 (偷个懒)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。