设计模式
Posted biyangqiang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式相关的知识,希望对你有一定的参考价值。
http://www.cnblogs.com/francfu/p/design-pattern-notes.html
http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html
https://blog.csdn.net/jason0539/article/details/23020989
a.创建型
1.简单工厂
package create.factory.simple; /** * 这里设计的abstract很巧妙 * @author bee * */ abstract class BMW { public BMW(){ } }
package create.factory.simple; public class BMW320 extends BMW{ public BMW320() { System.out.println("制造-->BMW320"); } }
package create.factory.simple; public class BMW523 extends BMW{ public BMW523(){ System.out.println("制造-->BMW523"); } }
package create.factory.simple; /** * PS: * 需要注意的地方,返回的类型 abstract类型 * @author bee * */ public class Factory { public BMW createBMW(int type){ switch (type) { case 320: return new BMW320(); case 523: return new BMW523(); default: break; } return null; } }
package create.factory.simple; public class Customer { public static void main(String[] args) { Factory factory = new Factory(); BMW bmw320 = factory.createBMW(320); BMW bmw523 = factory.createBMW(523); } }
制造-->BMW320
制造-->BMW523
优点:客户端不再负责对象的创建,而是把创建的责任丢给了具体的工厂类,客户端只负责对对象的调用,明确各个类的职责。
缺点:工厂使用静态方法来创建对象导致静态方法无法被继承。另外这个工厂类负责所有对象的创建,当具体产品不断增多需要不断修改工厂类增加相应判断逻辑不利于后期维护。
PS:适合 创建具体对象比较少的情况, 如果对象过多的话,还有添加创建工程的类
2.工厂方法模式
package create.factory.simple; /** * 这里设计的abstract很巧妙 * @author bee * */ abstract class BMW { public BMW(){ } } package create.factory.simple; public class BMW320 extends BMW{ public BMW320() { System.out.println("制造-->BMW320"); } } package create.factory.simple; public class BMW523 extends BMW{ public BMW523(){ System.out.println("制造-->BMW523"); } }
上面保持不变
package create.factory.method; /** * 有一个总工厂,每个工厂都有自己的实现,不用在参数中简单工厂中添加 太多的类型 * @author bee * */ public interface FactoryBMW { BMW createBMW(); }
package create.factory.method; public class FactoryBMW320 implements FactoryBMW{ @Override public BMW createBMW() { // TODO Auto-generated method stub return new BMW320(); } }
package create.factory.method; public class FactoryBMW523 implements FactoryBMW{ @Override public BMW createBMW() { // TODO Auto-generated method stub return new BMW523(); } }
package create.factory.method; public class Customer { public static void main(String[] args) { FactoryBMW320 factoryBMW320 = new FactoryBMW320(); BMW createBMW320 = factoryBMW320.createBMW(); FactoryBMW523 factoryBMW523 = new FactoryBMW523(); BMW bmw523 = factoryBMW523.createBMW(); } }
PS:一个大工厂变成小工厂,每个工厂都有继承的方法和自己的方法
工厂方法模式在简单工厂模式基础上继续进行职责的分配和包装。每一个产品都由一个具体的工厂来创建,把简单工厂模式中庞大的工厂类拆成一个个小的工厂类。每个具体的小工厂负责单独对象的创建,职责变小。
优点:如果有新的产品进入只需要新增一个创建产品工厂类和具体的产品类即可,不会影响到原来代码,增强系统拓展性。
缺点:需编写额外代码,增加了工作量。
简单工厂模式可以看作工厂模式的一个特例,单例模式就是创建后只能有一个实例。找盖房子的建筑商就相当于使用了创建者模式;找生产砖头的工厂就相当于使用了工厂模式;找配钥匙的师傅就相当于使用原型模式。(原型模式主要用于对象的复制)
创建者模式和抽象工厂模式的区别在于抽象工厂模式针对更细微的产品而创建,并且创建后产品的组装并不复杂。而创建者模式则是针对级别比较大的产品而创建,而且要创建产品的内部组装非常复杂。
3.抽象工厂
// ---产品类-------------
package create.factory.abstract1; //空调以及型号 public interface Aircondition { }
package create.factory.abstract1; public class AirconditionA implements Aircondition{ public AirconditionA(){ System.out.println("制造-->AirconditionA"); } }
package create.factory.abstract1; public class AirconditionB implements Aircondition{ public AirconditionB(){ System.out.println("制造-->AirconditionB"); } }
package create.factory.abstract1; //发动机以及型号 public interface Engine { }
package create.factory.abstract1; public class EngineA implements Engine{ public EngineA(){ System.out.println("制造-->EngineA"); } }
package create.factory.abstract1; public class EngineB implements Engine{ public EngineB(){ System.out.println("制造-->EngineB"); } }
//----------------工厂类----------------------------
package create.factory.abstract1; //创建工厂的接口 public interface AbstractFactory { //制造发动机 public Engine createEngine(); //制造空调 public Aircondition createAircondition(); }
package create.factory.abstract1; //为宝马320系列生产配件 public class FactoryBMW320 implements AbstractFactory{ @Override public Engine createEngine() { return new EngineA(); } @Override public Aircondition createAircondition() { return new AirconditionA(); } }
package create.factory.abstract1; //宝马523系列 public class FactoryBMW523 implements AbstractFactory { @Override public Engine createEngine() { return new EngineA(); } @Override public Aircondition createAircondition() { return new AirconditionB(); } }
///-----------------------测试类-------
package create.factory.abstract1; /** * 例子背景: 随着客户的要求越来越高,宝马车需要不同配置的空调和发动机等配件。于是这个工厂开始生产空调和发动机,用来组装汽车。这时候工厂有两个系列的产品:空调和发动机。 宝马320系列配置A型号空调和A型号发动机,宝马230系列配置B型号空调和B型号发动机。 概念: 抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。比如宝马320系列使用空调型号A和发动机型号A,而宝马230系列使用空调型号B和 发动机型号B,那么使用抽象工厂模式,在为320系列生产相关配件时,就无需制定配件的型号,它会自动根据车型生产对应的配件型号A。 * @author bee * *PS:使用的目的就是为了解耦 *总结: 无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去 在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加 入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之 后,它就演变成了工厂方法模式。 所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。 */ public class Consumer { public static void main(String[] args){ //生产宝马320系列配件 FactoryBMW320 factoryBMW320 = new FactoryBMW320(); factoryBMW320.createEngine(); factoryBMW320.createAircondition(); //生产宝马523系列配件 FactoryBMW523 factoryBMW523 = new FactoryBMW523(); factoryBMW523.createEngine(); factoryBMW523.createAircondition(); } }
4. 创建者模式
package create.factory.builder; public class Car{ public String engine; public String tyre; public String seat; public Car(){ } public String getEngine() { return engine; } public void setEngine(String engine) { this.engine = engine; } public String getTyre() { return tyre; } public void setTyre(String tyre) { this.tyre = tyre; } public String getSeat() { return seat; } public void setSeat(String seat) { this.seat = seat; } }
package create.factory.builder; public interface Builder { String buildEngine(); String buildTyre(); String buildSeat(); }
package create.factory.builder; public class CarBuilder implements Builder{ @Override public String buildEngine() { // 生产发动机 return "发动机"; } @Override public String buildTyre() { // 生产轮胎 return "轮胎"; } @Override public String buildSeat() { // 生产座椅 return "座椅"; } }
package create.factory.builder; public class CarDirector { CarBuilder cb;//将汽车的构建者导入 public CarDirector(CarBuilder cb){ this.cb=cb; } public Car constructCar(){ Car car=new Car(); car.setEngine(cb.buildEngine()); car.setTyre(cb.buildTyre()); car.setSeat(cb.buildSeat()); return car; } }
package create.factory.builder; /** * 三、建造者模式结构组成 Product: 表示被构造的复杂对象,其中包含需要构建的部件属性。 -------------------定义产品 Builder: 创建一个产品对象的各个部件指定抽象接口。 ------------------- 安装个过程 ConcreteBuilder: 实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示。 --------------构建安装 Director: 调用具体建造者角色以创建产品对象。 ------------------实现 * @author bee * */ public class Consumer { public static void main(String[] args) { CarDirector carDirector=new CarDirector(new CarBuilder()); Car car = carDirector.constructCar();///构建一个车 System.out.println(car.getEngine()+car.getTyre()+car.getSeat()); } }
----------------结构性------------------------
比如一台计算机启动,计算机在最外面,然后其他cpu,风扇都封装起来。只暴漏电脑启动方法,其他都含在内
优点:通过统一对外接口访问系统,避免了外部系统和子系统之间的直接联系从而降低了系统间的依赖和复杂度。
缺点:限制了外部系统对子系统的灵活调用。
2.适配器模式: 可以是系统接口和本来两个互不相容的另一个系统连接起来。
5.3 适用场景 5.3.1 系统需要使用现有的类,而这些类的接口不符合系统的接口。 5.3.2 想要建立一个可以重用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。 5.3.3 两个类所做的事情相同或相似,但是具有不同接口的时候。 5.3.4 旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,但我们不希望手动更改原有类的时候。 5.3.5 使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己的接口,但是要使用第三方组件接口的功能。
package create.struct.adapter; /** * 对象适配器 * @author bee * */ //已存在的、具有特殊功能、但不符合我们既有的标准接口的类 class Adaptee { public void specificRequest() { System.out.println("被适配类具有 特殊功能..."); } } //目标接口,或称为标准接口 interface Target { public void request(); } //具体目标类,只提供普通功能 class ConcreteTarget implements Target { public void request() { System.out.println("普通类 具有 普通功能..."); } } //适配器类,直接关联被适配类,同时实现标准接口 class Adapter implements Target{ // 直接关联被适配类 private Adaptee adaptee; // 可以通过构造函数传入具体需要适配的被适配类对象 public Adapter (Adaptee adaptee) { this.adaptee = adaptee; } public void request() { // 这里是使用委托的方式完成特殊功能 this.adaptee.specificRequest(); } } public class Client1 { public static void main(String[] args) { // 使用普通功能类 Target concreteTarget = new ConcreteTarget(); concreteTarget.request(); // 使用特殊功能类,即适配类, // 需要先创建一个被适配类的对象作为参数 Target adapter = new Adapter(new Adaptee()); adapter.request(); } }
3.代理模式:Spring中aop 拉皮条,明星中介 ,经纪人
4.装饰者模式:在一个类基础上再继承 一个类就是装饰者模式了
实际上Java 的I/O API就是使用Decorator实现的。
https://blog.csdn.net/jason0539/article/details/22713711
5.桥接模式:
桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化。桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。我们来看看关系图:
package create.struct.bridge; /** * 1.先定义方法 * @author bee * */ public interface Sourceable { public void method(); }
package create.struct.bridge; /** * 2.1方法分别实现 * @author bee * */ public class SourceSub1 implements Sourceable{ @Override public void method() { System.out.println("this is the first sub!"); } }
package create.struct.bridge; public class SourceSub2 implements Sourceable{ @Override public void method() { System.out.println("this is the second sub!"); } }
package create.struct.bridge; //定义一个桥,持有Sourceable的一个实例: public abstract class Bridge { private Sourceable source; public void method(){ source.method(); } public Sourceable getSource() { return source; } public void setSource(Sourceable source) { this.source = source; } }
package create.struct.bridge; public class MyBridge extends Bridge{ public void method(){ getSource().method(); } }
package create.struct.bridge; /** *设计好以后,不同的功能就可以根据不同的特点进行各自的实现,比如JDBC * @author bee * */ public class BridgeTest { public static void main(String[] args) { Bridge bridge = new MyBridge(); /*调用第一个对象*/ Sourceable source1 = new SourceSub1(); bridge.setSource(source1); bridge.method(); /*调用第二个对象*/ Sourceable source2 = new SourceSub2(); bridge.setSource(source2); bridge.method(); } }
this is the first sub!
this is the second sub!
6.组合模式: 比继承好一些。类似于二叉树
https://blog.csdn.net/jason0539/article/details/22642281
=================行为========================
1.模板模式 : Spring jdbcTempleate 执行的过程, 抽象类方法,然后实现类,调用方法
https://blog.csdn.net/xu__cg/article/details/53174505 https://blog.csdn.net/jason0539/article/details/45037535
2.观察者模式: 订阅和发布
view plaincopy public interface Observer { public void update(); } 两个实现类: [java] view plaincopy public class Observer1 implements Observer { @Override public void update() { System.out.println("observer1 has received!"); } } [java] view plaincopy public class Observer2 implements Observer { @Override public void update() { System.out.println("observer2 has received!"); } } Subject接口及实现类: [java] view plaincopy public interface Subject { /*增加观察者*/ public void add(Observer observer); /*删除观察者*/ public void del(Observer observer); /*通知所有的观察者*/ public void notifyObservers(); /*自身的操作*/ public void operation(); } [java] view plaincopy public abstract class AbstractSubject implements Subject { private Vector<Observer> vector = new Vector<Observer>(); @Override public void add(Observer observer) { vector.add(observer); } @Override public void del(Observer observer) { vector.remove(observer); } @Override public void notifyObservers() { Enumeration<Observer> enumo = vector.elements(); while(enumo.hasMoreElements()){ enumo.nextElement().update(); } } } [java] view plaincopy public class MySubject extends AbstractSubject { @Override public void operation() { System.out.println("update self!"); notifyObservers(); } } 测试类: [java] view plaincopy public class ObserverTest { public static void main(String[] args) { Subject sub = new MySubject(); sub.add(new Observer1()); sub.add(new Observer2()); sub.operation(); } } 输出: update self! observer1 has received! observer2 has received!
核心思想就是:当对象的状态改变时,同时改变其行为,很好理解!就拿QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作,而且你的好友也能看到你的状态,所以,状态模式就两点:1、可以通过改变状态来获得不同的行为。2、你的好友能同时看到你的变化。看图:
4.策略模式:不同方法执行不同的计算模式
5.责任链:看病、审批
6.命令模式: 做饭
7.访问者模式: 不太明白
不同的东西,不同价格
8.调停者模式:
9.备忘录模式(复制对象的某个时期的状态)
public class Original { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public Original(String value) { this.value = value; } public Memento createMemento(){ return new Memento(value); } public void restoreMemento(Memento memento){ this.value = memento.getValue(); } } [java] view plaincopy public class Memento { private String value; public Memento(String value) { this.value = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } [java] view plaincopy public class Storage { private Memento memento; public Storage(Memento memento) { this.memento = memento; } public Memento getMemento() { return memento; } public void setMemento(Memento memento) { this.memento = memento; } } 测试类: [java] view plaincopy public class Test { public static void main(String[] args) { // 创建原始类 Original origi = new Original("egg"); // 创建备忘录 Storage storage = new Storage(origi.createMemento()); 十条实用的jQuery代码片段