设计模式有用么?
必须有用啊。
通过总结成设计模式,可以通过一个名词来快速的描述出一段代码的结构,例如说个单例模式,大家一听就能想象出个大概。
设计模式中有些技巧,例如如何实现扩展性,可维护性,都是值得学习的。
熟悉设计模式一定是高手么?
不一定,但是高手一定熟悉涉及模式。
23种设计模式是1995年提出的,虽然大体概念不错,但是这么多年过去了,代码界早已天翻地覆无数回了。 所以可以参考,不能太迷信它。
很早就接触过设计模式,当时也是懂了,蓦然回首,发现基本全忘了。
还是方法不对,光理解不行,还要抓住要点,才能记得牢。
创建模式
工厂模式(factory)
创建和使用分开。
开闭原则。
解耦。
隐藏new对象的逻辑。
不使用工厂模式:
public static void main(String[] args) {
// 不用工厂方法
Benz benz = new Benz(); // 客户想要奔驰,直接new一辆
Bmw bmw = new Bmw(); // 客户想要宝马,直接new一辆
}
事实上,客户不需要知道如何new一辆车,只需要说我要需要什么车。
简单工厂模式(静态工厂模式)
定义:专门创建一个类来负责创建实例的工作,被创建的实例通常具有相同的父类。
简单工厂代码:
public class SimpleFactory {
public Car createCar(String requirement){
if(requirement.equals("benz")){
return new Benz();
}else if(requirement.equals("bmw")){
return new Bmw();
}else{
return new Car();
}
}
}
调用代码:
public static void main(String[] args) {
String requirement="benz";
Car car = new SimpleFactory().createCar(requirement);
}
工厂方法模式
话说我一直觉得工厂和抽象工厂差不多。 无非就是抽象工厂多实现了2个方法。
Factory代码:
public class Factory {
public Car createCar();
}
BenzFactory代码:
public class BenzFactory extends Factory{
@Override
public Car createCar() {
return new Benz();
}
}
BmwFactory代码:
public class BmwFactory extends Factory{
@Override
public Car createCar() {
return new Bmw();
}
}
抽象工厂模式
分离了具体的类。
原型模式(prototype)
目的 | 创建新对象比较复杂时,利用clone方法简化对象的创建,同时提高效率 |
---|---|
实现方式 | 重写clone方法 |
优点 | |
缺点 | 深克隆时代码可能比较复杂 需要为每个类配置一个clone方法,如果要调整,需要修改源码 |
应用场景 | 创建新对象比较复杂时,利用clone方法简化对象的创建,同时提高效率 不用初始化对象,可以动态的克隆当前对象以及他的状态 原始对象发生改变,克隆对象的也会发生相应的变化,无需修改代码 |
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
建造者模式(builder)
隐藏建造的细节。
一个builder实现类,用来封装部件的逻辑。
一个directory(经理,导演)/manager来组合要装配哪些部件。
经过这2层关系,可以具有高扩展性。
单例模式(singleton)
目的 | 一个类只有一个实例,免去频繁创建和销毁的过程。 |
---|---|
实现方式 | 构造函数私有化,保证在外部无法new对象 提供一个static方法获取当前实例(不同方案,实现不同) |
优点 | |
缺点 | 一般没有接口,扩展困难。 单例对象如果持有Context,那么很容易引发内存泄漏,此时需要注意传递给单例对象的Context最好是Application Context。 |
应用场景 | 对象频繁创建销毁,或者对象创建比较消耗资源 全局访问点,共享资源访问 如:controller就是用的单例 |
饿汉式:
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {
}
public static Singleton getInstance(){
return singleton;
}
}
懒汉式:
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance(){
if(null == singleton){
singleton = new Singleton();
}
return singleton;
}
}
结构模式
外观模式(facade)
代理模式(proxy)
适配器模式(adapter)
组合模式(composite)
装饰者模式(decorator 或 wrapper)
wrapper模式的实现过程:
wrapper类实现该接口
wrapper类引如该接口实例
写入新方法
覆盖接口方法,新方法可以添加再接口方法的前后
装饰着模式和代理模式的区别
到decorator模式的时候,我一看,这不就是代理模式么?
实现上确实很类似,但是也有些区别。
对装饰器模式来说,装饰者(decorator)和被装饰者(decoratee)都实现同一个 接口。对代理模式来说,代理类(proxy class)和真实处理的类(real class)都实现同一个接口。他们之间的边界确实比较模糊,两者都是对类的方法进行扩展,具体区别如下:
1、装饰器模式强调的是增强自身,在被装饰之后你能够在被增强的类上使用增强后的功能。增强后你还是你,只不过能力更强了而已;代理模式强调要让别人帮你去做一些本身与你业务没有太多关系的职责(记录日志、设置缓存)。代理模式是为了实现对象的控制,因为被代理的对象往往难以直接获得或者是其内部不想暴露出来。
2、装饰模式是以对客户端透明的方式扩展对象的功能,是继承方案的一个替代方案;代理模式则是给一个对象提供一个代理对象,并由代理对象来控制对原有对象的引用;
3、装饰模式是为装饰的对象增强功能;而代理模式对代理的对象施加控制,但不对对象本身的功能进行增强;
桥接模式(bridge)
感觉这个模式,就是如果可能有多个组合,一个采用继承。一个采用set类作为属性的方式。
实现组合功能。
享元模式(flyweight)
行为模式
模板模式(template)
备忘录模式(memento)
观察者模式(observer)
在看mq的@RabbitListener注解时,想它的机制,突然发现可能和观察者模式有关。
要点:
java有现成的api,主要就两个。
第一。
我们必须extends Java.util.Observer才能真正使用它:
1.提供Add/Delete observer的方法;
2.提供通知(notisfy) 所有observer的方法;
第二。
Observable类。
在每个属性的变动时,都设置变动,并通知到所有观察者。
产品类
//产品类 可供Jsp直接使用UseBean调用 该类主要执行产品数据库插入 更新
public class product extends Observable{
private String name;
private float price;
public String getName(){ return name;}
public void setName(){
this.name=name;
//设置变化点
setChanged();
notifyObservers(name);
}
public float getPrice(){ return price;}
public void setPrice(){
this.price=price;
//设置变化点
setChanged();
notifyObservers(new Float(price));
}
//以下可以是数据库更新 插入命令.
public void saveToDb(){
.....................
}
两个观察者
观察者1:
//观察者NameObserver主要用来对产品名称(name)进行观察的
public class NameObserver implements Observer{
private String name=null;
public void update(Observable obj,Object arg){
if (arg instanceof String){
name=(String)arg;
//产品名称改变值在name中
System.out.println("NameObserver :name changet to "+name);
}
}
}
观察者2:
//观察者PriceObserver主要用来对产品价格(price)进行观察的
public class PriceObserver implements Observer{
private float price=0;
public void update(Observable obj,Object arg){
if (arg instanceof Float){
price=((Float)arg).floatValue();
System.out.println("PriceObserver :price changet to "+price);
}
}
}
调用
public class Test {
public static void main(String args[]){
Product product=new Product();
NameObserver nameobs=new NameObserver();
PriceObserver priceobs=new PriceObserver();
//加入观察者
product.addObserver(nameobs);
product.addObserver(priceobs);
product.setName("橘子红了");
product.setPrice(9.22f);
}
}
你会在发现下面信息::
NameObserver :name changet to 橘子红了
PriceObserver :price changet to 9.22
这说明观察者在行动了.!!
职责链模式(Chain of Responsibility)
命令模式(command)
状态模式(state)
策略模式(strategy)
中介者模式(mediator)
解释器模式(interpreter)
访问者模式(visitor)
①装饰器模式特点:
(1) 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
(2) 装饰对象包含一个真实对象的引用(reference)
(3) 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
(4) 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。