您的位置:首页 > 编程语言 > Java开发

java设计模式

2016-09-27 11:48 609 查看
一、设计模式的分类

创建型模式:

结构型模式:

行为型模式:

二、设计模式的六大原则

1、开闭原则

所谓开闭原则就是对扩展开放,对修改关闭。这样做是为了不修改原有代码,而又在原有代码的功能上实现新的功能,这就是为何要使用面向接口编程的原因。

2、里氏代换原则

任何基类可以出现的地方,子类一定可以出现。

3、依赖倒转原则

这是开闭原则的基础,直接对接口编程,依赖于接口,而不依赖于具体类。

4、接口隔离原则

使用多个隔离的接口比使用单个接口好。这个原则的目的就是降低耦合,降低依赖。

5、迪米特法则(最少知道原则)

一个实体最少的与其他实体发生相互关系,降低耦合。

6、合成复用原则

尽量使用合成/聚合方式,而不是使用继承。

三、设计模式详解

1、创建型模式

(1)单列模式

1)单列模式的作用:

确保某个类在整个系统中仅仅只有一个实例,并且类自动初始化这个实例。

2)单列模式的分类:

懒汉式单列模式:在第一次调用这个类的对象的时候进行实例化。

饿汉式单列模式:在类被调用的时候就已经初始化了对象。

3)饿汉式单列模式和懒汉式单列模式的区别:

懒汉式单列模式不是线程安全的,但是饿汉式单列模式是线程安全的。

懒汉式单列模式在第一次调用的时候比较慢,而饿汉式单列模式第一次调用的时候比懒汉式单列模式较快,但是后面应用的时候两者的速度就相等了。

注意:懒汉式单列模式依然可以实现线程安全,仅仅需要将获取对象的方法添加同步关键词。

4)单列模式的实例:

//懒汉式单列模式,在第一次调用的时候实例化自己
class Singleton1{
private Singleton1(){};
private static Singleton1 singleton1;
//静态工厂方法
public static Singleton1 getInstance(){
if (singleton1 == null) {
singleton1 = new Singleton1();
}
return singleton1;
}
}

//饿汗式单列模式 ,在类初始化的时候,已经自行实例化
class Singleton2{
private Singleton2(){};
private static final Singleton2 singleton2 = new Singleton2();
//静态工厂方法
public static Singleton2 getInstance(){
return singleton2;
}
}

(2)工厂模式

工厂模式分为工厂方法模式和抽象工厂模式。而简单工厂模式是工厂方法模式的一个特例。

1)简单工厂模式

         简单工厂模式又称静态工厂方法模式。

/**
* 简单工厂方法模式
* @author LiuTao
*
*/
//首先创建二者的共同接口,既抽象产品
interface Sender{
public void send();
}

//创建两个具体产品,实现抽象产品
class SmsSender implements Sender{
@Override
public void send() {
System.out.println("send sms");
}
}

class EmailSender implements Sender{
@Override
public void send() {
System.out.println("send email");
}
}

//创建工厂类
class Factory{
public Sender product(String type){
switch (type) {
case "sms":
return new SmsSender();
case "email":
return new EmailSender();
default:
System.out.println("请输入正确的值");
return null;
}
}
}
2)多个工厂方法模式

/**
* 多个工厂方法模式
* @author LiuTao
*
*/
class SendFactory{
public Sender smsProduct(){
return new SmsSender();
}

public Sender EmailProduct(){
return new EmailSender();
}
}
3)静态 工厂方法模式
/**
* 静态工厂方法模式,将多个工厂方法模式的每个方法设置为静态的即可
* @author LiuTao
*
*/
class StaticSendFactory{
public static Sender smsProduct(){
return new SmsSender();
}

public static Sender emailProduct(){
return new EmailSender();
}
}
4)抽象工厂方法模式

针对抽象工厂方法模式,很好地实现了降低耦合。增加一个产品仅仅需要增加一个具体工厂即可。

/**
* 抽象工厂模式,很好的遵守了开闭原则,如果增加了一个产品,则只需增加相应的具体产品工厂类,而不需要去修改工厂类
* @author LiuTao
*
*/
//创建抽象工厂
interface AbstractFactory{
public Sender product();
}

//创建两个具体工厂
class SmsFactory implements AbstractFactory{
@Override
public Sender product() {
return new SmsSender();
}
}

class EmailFactory implements AbstractFactory{
@Override
public Sender product() {
return new EmailSender();
}
}
public class FactoryExample {
public static void main(String[] args) {
//测试简单工厂方法模式
Factory factory = new Factory();
Sender sender = factory.product("sms");
sender.send();

//测试多个工厂方法模式
SendFactory sendFactory = new SendFactory();
Sender sender2 = sendFactory.EmailProduct();
sender2.send();

//测试静态工厂方法模式
Sender sender3 = StaticSendFactory.smsProduct();
sender3.send();

//测试抽象工厂方法模式
AbstractFactory abstractFactory = new SmsFactory();
Sender sender4 = abstractFactory.product();
sender4.send();
}
}


2、结构型模式

(1)适配器模式

适配器模式的作用是将类的接口转换成客户端所需要的接口,目的是消除接口不匹配带来的兼容性问题。

适配器模式分为类适配器模式,对象适配器模式,接口适配器模式。

1)类适配器模式:

当一个类(源类)需要需要拥有另一个类(目标类)里面的功能的时候,可以创建一个新类(适配器类)来继承源类,并且实现目标类。

/**
* 类的适配器模式
* @author LiuTao
*
*/
//创建待适配的类
class Source{
public void method1(){
System.out.println("this is orginal method");
}
}

//创建目标接口
interface Target{
public void method1();
public void method2();
}

//创建适配器
class Adapter extends Source implements Target{

@Override
public void method2() {
System.out.println("this is target method");
}

}
2)对象适配器

当需要一个类满足新接口的时候,可以创建一个新类实现这个接口,同时持有这个类的对象。

/**
* 对象适配器模式
* @author LiuTao
*
*/
class Wrapper implements Target{
private Source source;
public Wrapper(Source source) {
super();
this.source = source;
}
@Override
public void method1() {
source.method1();
}
@Override
public void method2() {
System.out.println("this is target method");
}
}
3)接口的适配器模式

如果不想实现一个接口里面的所有方法,那么可以创建一个类实现该接口,然后让之前想要实现这个接口的类继承这个类,就可以实现部分方法了。

/**
* 对象适配器模式
* @author LiuTao
*
*/
class Wrapper implements Target{
private Source source;
public Wrapper(Source source) {
super();
this.source = source;
}
@Override
public void method1() {
source.method1();
}
@Override
public void method2() {
System.out.println("this is target method");
}
}
public class AdapterExample {
public static void main(String[] args) {
//测试类的适配器模式
Target target = new Adapter();
target.method1();
target.method2();

//测试对象适配器模式
Source source = new Source();
Target target2 = new Wrapper(source);
target2.method1();
target2.method2();

//测试接口适配器模式
Sourceable sourceable1 = new SourceSub1();
Sourceable sourceable2 = new SourceSub2();
sourceable1.method1();
sourceable1.method2();
sourceable2.method1();
sourceable2.method2();
}
}


(2)组合模式

(3)装饰模式

装饰模式又叫做包装模式。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

1)装饰模式中的角色:

抽象构件角色:给出一个抽象接口,以规范准备接收附加责任的对象(定义装饰者和被装饰者的共有方法)。

具体构件角色:定义一个将要接收附加责任的类(被装饰者,实现抽象构件角色)。

抽象装饰角色:持有一个构件对象的实例,并定义一个与抽象构件一直的接口(持有构件对象,并在方法中调用构件对象的方法)。

具体装饰角色:负责给构件对象贴上附加的责任(继承抽象装饰角色,注意在构造器和方法中super的用法)。

public class DecoratorExample {
public static void main(String[] args) {
TheGreatestSage sage = new Monkey();
// 第一种写法
TheGreatestSage bird = new Bird(sage);
TheGreatestSage fish = new Fish(bird);
// 第二种写法
//TheGreatestSage fish = new Fish(new Bird(sage));
fish.move();
}
}

//抽象构件角色
interface TheGreatestSage{
public void move();
}

//具体构件角色
class Monkey implements TheGreatestSage{
@Override
public void move() {
System.out.println("Monkey Move");
}
}

//抽象装饰角色
class Change implements TheGreatestSage{
private TheGreatestSage sage;
public Change(TheGreatestSage sage) {
this.sage = sage;
}
@Override
public void move() {
sage.move();
}
}

//具体装饰角色
class Fish extends Change{
public Fish(TheGreatestSage sage) {
super(sage);
}

@Override
public void move() {
super.move();
System.out.println("Fish Move");
}
}

//具体装饰角色
class Bird extends Change{
public Bird(TheGreatestSage sage) {
super(sage);
}

@Override
public void move() {
super.move();
System.out.println("Bird Move");
}
}


(4)外观模式

适用于有多个子系统,但是不需要全部向用户展示,只需要用户知道使用这些子系统的途径。

要点:外观模式为复杂的子系统提供了一个简单的接口,并不为子系统添加新的功能和行为。

  外观模式实现了子系统与客户之间的松散耦合。

  外观模式注重的是简化接口。

public class FacaderExample {
public static void main(String[] args) {
//测试外观模式
Computer computer = new Computer();
computer.startUp();
}
}

//创建子系统角色
class CPU{
public void startUp(){
System.out.println("CPU start up");
}
}

class Memory{
public void startUp(){
System.out.println("Memory start up");
}
}
class Disk{
public void startUp(){
System.out.println("Disk start up");
}
}

//创建门面角色
class Computer{
private CPU cpu;
private Memory memory;
private Disk disk ;
public Computer() {
cpu = new CPU();
memory = new Memory();
disk = new Disk();
}

public void startUp() {
cpu.startUp();
memory.startUp();
disk.startUp();
}

}


(5)代理模式

1)代理模式的作用:为其他对象提供一种代理以控制对这个对象的访问。

2)代理模式中的角色:

抽象角色:定义代理对象和被代理对象的公共接口。

代理角色:代理角持有被代理角色,同时在代理角色的公共接口方法中调用了真实角色的方法,可以对真实角色的方法进行扩展。

真实角色:被代理对象,实现了抽象角色。

3)应用场景:对已有类功能的扩展,同时不将被代理类的信息显示给使用者。

4)应用实例:

public class ProxyExample {
public static void main(String[] args) {
//测试代理模式
Sourceable source = new Proxy();
source.method();
}
}

//创建公共接口
interface Sourceable{
public void method();
}

//创建被代理类
class Source implements Sourceable{
@Override
public void method() {
System.out.println("the orginal method");
}
}

//创建代理类
class Proxy implements Sourceable{
private Sourceable source;

public Proxy() {
super();
source = new Source();
}

@Override
public void method() {
beforeProxy();
source.method();
afterProxy();
}

public void beforeProxy(){
System.out.println("before proxy");
}
public void afterProxy(){
System.out.println("after proxy");
}
}


3、行为型模式

(1)观察者模式

1)观察者模式的作用:观察者模式定义了一种一对多的对应关系,让多个观察者共同监听某一主题对象,当主题对象发生改变时,会通知所有观察者,从而观察者做出相应的改变。

2)观察者中的角色:

抽象主题角色:持有观察者,并且拥有对观察者进行增加、删除以及通知观察者的方法。

具体主题角色:继承抽象主题对象,并且添加了自己改变的方法,方法中调用通知观察者的方法。

抽象观察者角色:定义了自我更新的方法。

具体观察者角色:实现抽象观察者接口,并且实现了自我更新方法的具体内容。

3)观察者模式的分类:

推模型观察者模式:向观察者传入具体的参数,然后观察者根据需要作出相应的改变。

拉模型观察者模式:拉模型观察者模式通常是将自己传递给观察者,然后观察者按照需要获取主题对象的参数和,然后作出相应的改变。

3)观察者模式的应用场景:

当一个抽象模型的两个方面,其中一个方面依赖于另一个方面。将这两者封装在独立的对象中,使他们独自改变和维护。

当对一个对象的改变需要改变其他对象的时候,而又不知道有多少个对象需要改变。

当一个对象必须通知其他对象,而又不知道其他对象是谁。也就是不希望这些对象是紧密耦合。

4)观察者模式的应用实例:

public class ObserverExample {
public static void main(String[] args) {
//创建主题对象
ConcreteSubject concreteSubject = new ConcreteSubject();
//创建观察者对象
Observer observer = new ConcreteObserver();
//将观察者对象添加到主题对象
concreteSubject.attach(observer);
//改变主题对象角色
concreteSubject.change("new state");
}
}

/**
*推模型观察者模式
*/
//抽象主题角色
abstract class Subject{
//用来保存注册的观察者对象
private List<Observer> list = new ArrayList<Observer>();

//注册观察者对象
public void attach(Observer observer){
list.add(observer);
System.out.println("Attached an observer");
}

//删除观察者对象
public void remove(Observer observer){
list.remove(observer);
System.out.println("Remove an observer");
}

//通知所有注册的观察者对象
public void nodifyObservers(String newState){
for (Observer observer : list) {
observer.update(newState);
}
}
}

//具体主题角色
class ConcreteSubject extends Subject{
private String state;
public String getState(){
return state;
}
public void change(String newState){
state = newState ;
System.out.println("主题状态为:"+state);
//状态发生改变,通知各个观察者
this.nodifyObservers(state);
}
}

//抽象观察者角色
interface Observer{
public void update(String state);
}

//具体观察者角色
class ConcreteObserver implements Observer{
//观察者的状态
private String observerState;
@Override
public void update(String state) {
//更新观察者的状态,使其与目标的状态保持一致
observerState = state;
System.out.println("状态为:"+observerState);
}

}

/**
*拉模型观察者模式
*/
//抽象观察者
interface Observer1{
//更新接口,之前传入的是具体的参数,现在传入主题对象,又观察者自己按需获取想要的参数。
public void update(Subject subject);
}

//具体观察者
class ConcreteObserver1 implements Observer1{
private String observerState;

@Override
public void update(Subject subject) {
observerState = ((ConcreteSubject)subject).getState();
System.out.println("观察者状态为:"+observerState);
}
}


(2)策略模式

1)策略模式的作用:

可以提供管理相关算法的算法簇的办法,并且可以将共有方法移到抽象类中。而且可以避免使用条件语句等多重循环。

2)策略模式中的角色:

环境角色:持有策略角色,并且调用相应的方法。

抽象策略角色:定义了策略接口,也就是策略类要实现什么功能。

具体策略角色:实现了抽象策略接口。

3)策略模式的应用场景:

4)策略模式的实例:

public class StrategyExample {

public static void main(String[] args) {
//测试策略模式
Price price = new Price(new AdvancedMemberStrategy());
System.out.println("计算后的价格是:"+price.quote(12.12));
}
}

//创建抽象策略角色
interface MemberStrategy {
public double calPrice(double booksPrice);
}

//创建具体策略角色
class PrimaryMemberStrategy  implements MemberStrategy{

@Override
public double calPrice(double booksPrice) {
return booksPrice;
}

}
class IntermediateMemberStrategy  implements MemberStrategy{

@Override
public double calPrice(double booksPrice) {
return booksPrice*0.9;
}

}
class AdvancedMemberStrategy   implements MemberStrategy{

@Override
public double calPrice(double booksPrice) {
return booksPrice*0.8;
}

}

//创建环境角色
class Price{
MemberStrategy memberStrategy;
public Price(MemberStrategy memberStrategy) {
this.memberStrategy = memberStrategy;
}

public double quote(double bookPrice){
return this.memberStrategy.calPrice(bookPrice);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: