Java:GOF的23种设计模式(上)

    最近学习设计模式,主要参考两本书《大话设计模式》和《Java设计模式》,而两本书的重要参考书目都有大名鼎鼎的GOF的《设计模式》。等到自己的理解能力足够时,一定会继续研读《设计模式》、《Head First设计模式》这些圣经。现在的学习就当是一种了解,虽知现在学习不可能很深入,理解得非常浅显,就当是为以后做个铺垫,某年某月某日看到某些代码时,会惊觉这怎么这么像之前学的那些设计模式的?我想那时一定会有深刻的印象,从而了解到精髓,这就达到了学习的目的了。知识不能等到要用时才真正去学,应该不断积累。

    这篇文章主要是集中了23种模式的代码Demo,而不会有太多的讲解,因为大家学习都肯定是先从看书过来的,有了最初步的认识的。这些代码,有些是从《大话设计模式》(C#语言)一书中改写过来的;有些是从网上看到一些比较好的例子然后模仿写下来的;有些则是自己写的。这篇文章还有这些代码当是自己的又一次复习和笔记整理吧(整个学习才接近一个礼拜,所以不可能会深入的)

    现在正式开始,每个实例代码前面只会有几句自己看书时做的小笔记(有些是意思一样的,只是摘录的地方不同),按照《Java设计模式》的章节顺序来写。

目录:

一:接口型模式  1)适配器模式;2)外观模式;3)组合模式;4)桥接模式 

二:责任型模式  1)单例模式;2)观察者模式;3)中介者模式;4)代理模式;5)责任链模式;6)享元模式

三:构造型模式  1)建造者模式;2)工厂方法模式;3)抽象工厂模式;4)原型模式;5)备忘录模式

四:操作型模式  1)模板方法模式;2)状态模式;3)策略模式;4)命令模式;5)解释器模式

五:拓展型模式  1)装饰器模式;2)迭代器模式;3)访问者模式


一:接口型模式

(1)适配器模式(Adapter)

1.适配器模式的宗旨是,保留现有类提供的服务,向客户提供接口,以满足客户的期望。
2.使用一个已经存在的类,如果它的接口也就是方法和你的需求不同时,可以考虑用适配器模式。

①Target类,客户期待的接口

public class Target {
	public void request() {
		System.out.println("欧美家庭使用110v电压");
	}
}
②Adaptee类,需要适配的类

public class Adaptee {
	public void specialRequest() {
		System.out.println("中国家庭使用110v电压");
	}
}
③Adapter类,把客户接口转换成目标接口

public class Adapter extends Target{
	private Adaptee adaptee = new Adaptee(); //封装一个Adaptee对象
	public void request() {
		adaptee.specialRequest();
	}
}
④Test类

public class Test {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Target target = new Adapter(); //通过适配器,此时调用的是适配的类的方法
		target.request();
	}
}

(2)外观模式(Facade)

1.外观模式的目的在于提供一个接口,使子系统更加容易使用
2.为子系统的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
3.外观模式为设计粗糙或高度复杂的遗留代码(即子系统)提供一个简单的接口,使新系统与Facade对象交互。

①一个步骤接口

public abstract class Step {
	public abstract void step();
}

②三个子系统类

public class StepOne extends Step {
	public void step() {
		System.out.println("手伸入袋子");
	}
}
public class StepTwo extends Step{
	public void step() {
		System.out.println("掏出钥匙");
	}
}
public class StepThree extends Step {
	public void step() {
		System.out.println("打开门");
	}
}

③外观类,对子系统的属性或方法进行组合,以备外界调用

public class Facade {
	private Step step1 = new StepOne();
	private Step step2 = new StepTwo();
	private Step step3 = new StepThree();
	public void step() {
		step1.step();
		step2.step();
		step3.step();
	}
}

④Test类

public class Test {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		// Step step1 = new StepOne();
		// Step step2 = new StepTwo();
		// Step step3 = new StepThree();
		// step1.step();
		// step2.step();
		// step3.step();
		Facade facade = new Facade(); //通过外观类的组装,使子系统更加容易使用
		facade.step();
	}
}

(3)组合模式(Composite)

1.组合模式的设计意图在于:让用户能够用统一的接口处理单个对象以及对象组合
2.将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象使用具有一致性
3.需求中是体现部分与整体层次结构,希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象。

①Component接口

public abstract class Component {
	protected String name;
	public Component(String name) {
		this.name = name;
	}	
	public abstract void add(Component c);
	public abstract void remove(Component c);
	public abstract void display(int depth);
}
②Leaf类,表示单个对象

public class Leaf extends Component {
	public Leaf(String name) {
		super(name);
		// TODO 自动生成的构造函数存根
	}
	@Override
	public void add(Component c) {
		// TODO 自动生成的方法存根
	}
	@Override
	public void remove(Component c) {
		// TODO 自动生成的方法存根
	}
	@Override
	public void display(int depth) {
		// TODO 自动生成的方法存根
		for (int i = 0; i < depth; i++) {
			System.out.print("-");
		}
		System.out.println(name);
	}

}
③Composite类,表示对象组合

import java.util.ArrayList;
import java.util.List;
public class Composite extends Component {
	private List<Component> components = new ArrayList<Component>();
	public Composite(String name) {
		super(name);
		// TODO 自动生成的构造函数存根
	}
	@Override
	public void add(Component c) {
		// TODO 自动生成的方法存根
		components.add(c);
	}
	@Override
	public void remove(Component c) {
		// TODO 自动生成的方法存根
		components.remove(c);
	}
	@Override
	public void display(int depth) {      //区分单个对象和组合对象
		// TODO 自动生成的方法存根
		for (int i = 0; i < depth; i++) {
			System.out.print("-");
		}
		System.out.println(name);
		for (Component component : components) {     
			component.display(depth + 2);
		}
	}

}
④Test类

public class Test {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Composite root = new Composite("root");
		root.add(new Leaf("leaf1"));	
		Composite branch1 = new Composite("branch1");
		branch1.add(new Leaf("leaf2"));
		Composite branch2 = new Composite("branch2");
		branch2.add(new Leaf("leaf3"));
		branch2.add(new Leaf("leaf3"));		
		branch1.add(branch2);
		root.add(branch1);
		root.display(1);
	}
}

打印结果:

-root
---leaf1
---branch1
-----leaf2
-----branch2
-------leaf3
-------leaf3

(4)桥接模式(Bridge)

1.桥接模式的意图是将抽象与抽象方法的实现相互分离,这样它们就可以独自变化。
2.将抽象部分与它的实现部分分离,使它们可以独自变化。
3.实现系统有多角度分类,每一种分类都可能变化,那么就把这种多角度分离出来让它们独自变化,减少它们之间的耦合性。

假设一颗继承树如下:

--手机

----手机品牌A

------2G手机品牌A

------3G手机品牌A

------4G手机品牌A

----手机品牌B

------2G手机品牌B

......

上面这种模式如果每增加一个手机品牌或者出产一种新的5G、6G手机都会造成很高的耦合。使用桥接模式可以很好地解耦:

①品牌抽象类

package bridge;
public abstract class Brand {
	protected XGPhone xgPhone; // key
	public Brand(XGPhone xgPhone) {
		this.xgPhone = xgPhone;
	}
	public abstract void run();
}
②手机模式抽象类
package bridge;
public abstract class XGPhone {
	public abstract void run();
}
③品牌继承类

package bridge;
public class Brand_1 extends Brand {
	public Brand_1(XGPhone xgPhone) {
		super(xgPhone);
	}
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		System.out.print(this);
		xgPhone.run();
	}
	public String toString() {
		return "品牌1的";
	}
}
package bridge;
public class Brand_2 extends Brand {
	public Brand_2(XGPhone xgPhone) {
		super(xgPhone);
	}
	@Override
	public void run() {
		// TODO 自动生成的方法存根
		System.out.print(this);
		xgPhone.run();
	}
	public String toString() {
		return "品牌2的";
	}
}
③手机模式继承类

package bridge;
public class X2GPhone extends XGPhone {
	public void run(){
		System.out.println("2G手机");
	}
}
package bridge;
public class X3GPhone extends XGPhone {
	public void run(){
		System.out.println("3G手机");
	}
}
package bridge;
public class X4GPhone extends XGPhone {
	public void run(){
		System.out.println("4G手机");
	}
}
④Test类

package bridge;
public class Test {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Brand brand1 = new Brand_1(new X2GPhone());
		brand1.run();
	}

}

二:责任性模式

(1)单例模式(Singleton)

1.单例模式的宗旨在于确保某个类只有一个实例,并且为之提供一个全局访问点。
2.通过隐藏构造器和提供对创建对象的单个访问点,单例模式就能够将类的职责集中于类的某个单个实例中。

①Singleton类

public class Singleton {
	private static Singleton instance;
	private static Object lock = Singleton.class;
	private Singleton() { // 将构造器设为私有

	}
	// 获得类实例的唯一全局访问点
	public static Singleton getInstance() {
		// 确保只有一个实例
		synchronized (lock) {
			if (instance != null) {
				instance = new Singleton();
			}
			return instance;
		}
	}
}
②Test类

public class Test {
	public static void main(String[] args) {
		Singleton s1 = Singleton.getInstance();
		Singleton s2 = Singleton.getInstance();
		System.out.println(s1 == s2);
	}
}

(2)观察者模式(Observer)

1.观察者模式的宗旨是在多个对象之间定义一对多的关系,以便当一个对象状态改变的时候,其他所有依赖于这个对象的对象都能够得到通知,并自动更新。
2.观察者模式又叫做发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

①抽象通知者

public abstract class Notifier {
	public abstract void attach(Observer observer);
	public abstract void detach(Observer observer);
	public abstract void notifyObservers();
}
②抽象观察者

public abstract class Observer {
	protected String name;
	public abstract void update();
	public Observer(String name) {
		this.name = name;
	}
}
③具体通知者

import java.util.ArrayList;
import java.util.List;
public class SecretaryNotifier extends Notifier {
	private List<Observer> observers = new ArrayList<Observer>();
	@Override
	public void attach(Observer observer) {
		// TODO 自动生成的方法存根
		observers.add(observer);
	}
	@Override
	public void detach(Observer observer) {
		// TODO 自动生成的方法存根
		observers.remove(observer);
	}
	@Override
	public void notifyObservers() { 
		// TODO 自动生成的方法存根
		for (Observer observer : observers) {
			System.out.print("秘书说:");
			observer.update();
		}
	}

}
④具体观察者

public class NBAObserver extends Observer {
	public NBAObserver(String name) {
		super(name);
		// TODO 自动生成的构造函数存根
	}
	@Override
	public void update() {
		// TODO 自动生成的方法存根
		System.out.println(name + ",老板回来了,别看NBA了");
	}
}
public class SleepObserver extends Observer {
	public SleepObserver(String name) {
		// TODO 自动生成的构造函数存根
		super(name);
	}
	@Override
	public void update() {
		// TODO 自动生成的方法存根
		System.out.println(name + ",老板回来了,别睡了");
	}
}
④Test类

public class Test {
	public static void main(String[] args) {
		Notifier notifier = new SecretaryNotifier();
		Observer observer = new SleepObserver("小明");
		Observer observer2 = new SleepObserver("小东");
		Observer observer3 = new NBAObserver("小强");
		notifier.attach(observer);
		notifier.attach(observer2);
		notifier.attach(observer3);
		notifier.notifyObservers(); // 一次更新所有
	}
}
打印结果:

秘书说:小明,老板回来了,别睡了
秘书说:小东,老板回来了,别睡了
秘书说:小强,老板回来了,别看NBA了

(3)中介者模式(Mediator)

1.观察者模式通过尽可能缩小一个对象应对其他对象承担的责任范围来支持这种责任分配;单例模式将责任集中于其他对象都可以访问和复用的某个特定对象中;与单例模式类似的是,中介者模式也对责任进行了集中,不过这种模式只是对某个特定对象集合的责任进行集中,而不是对整个系统的其他所有对象的责任进行集中。
2.中介者模式的意图是定义一个对象,该对象将对象集合之间的交互封装起来。利用该模式可以降低对象之间的耦合程度,避免对象之间的显示引用,还可以让对象间的交互独立变化。
3.中介者模式,用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使耦合松散,而且可以独立地改变他们之间的交互。

①中介者类,封装需要交互的类

public class Mediator {
	private ConColleague1 cc1;
	private ConColleague2 cc2;
	public void setCC1(ConColleague1 cc1) {
		this.cc1 = cc1;
	}
	public void setCC2(ConColleague2 cc2) {
		this.cc2 = cc2;
	}
	public void sendMessage(String message, Colleague colleague) { //具体交互
		if (colleague == cc1) {
			cc2.getMessage(message);
		} else {
			cc1.getMessage(message);
		}
	}
}
②抽象同事类,它的子类是一些会产生交互的类

public abstract class Colleague {
	protected Mediator mediator;

	public Colleague(Mediator mediator) {
		this.mediator = mediator;
	}
}
③具体同事类

public class ConColleague1 extends Colleague {
	public ConColleague1(Mediator mediator) {
		super(mediator);
		// TODO 自动生成的构造函数存根
	}
	public void sendMessage(String message) {
		mediator.sendMessage(message, this);
	}
	public void getMessage(String message) {
		System.out.print("同事1得到的信息:" + message);
	}
}
public class ConColleague2 extends Colleague {
	public ConColleague2(Mediator mediator) {
		super(mediator);
		// TODO 自动生成的构造函数存根
	}
	public void sendMessage(String message) {
		mediator.sendMessage(message, this);
	}
	public void getMessage(String message) {
		System.out.print("同事2得到的信息:" + message);
	}
}
④Test类

public class Test {
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Mediator mediator = new Mediator();
		// 认识相同的中介者,通信封装在中介者类中
		ConColleague1 cc1 = new ConColleague1(mediator);
		ConColleague2 cc2 = new ConColleague2(mediator);
		mediator.setCC1(cc1);
		mediator.setCC2(cc2);
		cc1.sendMessage("你好啊");
	}

}


(4)代理模式(Proxy)

1.代理模式的意图在于为对象提供一个代理或者占位来控制对该对象的访问
2.代理模式,为其他对象提供一种代理以控制对这个对象的访问

①Subject接口

public abstract class Subject {
	public abstract void request();
}
②RealSubject

public class RealSubject extends Subject {
	@Override
	public void request() {
		// TODO 自动生成的方法存根
		System.out.println("real request");
	}
}
③ProxySubject

public class ProxySubject extends Subject {
	RealSubject rs = new RealSubject();
	@Override
	public void request() {
		// TODO 自动生成的方法存根
		rs.request();
	}
}
④Test类

public class Test {
	public static void main(String[] args) {
		ProxySubject proxySubject = new ProxySubject();
		proxySubject.request(); // 真正的对象是rs,proxySubject起到一个代理作用
	}
}

(5)责任链模式(Chain Of Responsibility)

1.责任链模式可让每个对象都有一次机会决定自己是否处理请求,以便于避免请求的发送者与其接收者的耦合。
2.使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象可以处理它为止。

①抽象Handler类

public abstract class Handler {
	protected Handler leader;
	protected String name;
	public Handler(String name) {
		this.name = name;
	}
	public void setLeader(Handler leader) { // key
		this.leader = leader;
	}

	public abstract void handleRequest(String requestType);
}
②具体Handler类

public class ConcreteHandler_1 extends Handler {
	public ConcreteHandler_1(String name) {
		super(name);
		// TODO 自动生成的构造函数存根
	}
	@Override
	public void handleRequest(String requestType) {
		// TODO 自动生成的方法存根
		if (requestType == "请假") {
			System.out.println(name + "批准请假");
		} else if (leader != null) { // 如果无法处理,传递给上一级
			leader.handleRequest(requestType);
		}
	}
}
public class ConcreteHandler_2 extends Handler {
	public ConcreteHandler_2(String name) {
		super(name);
		// TODO 自动生成的构造函数存根
	}
	@Override
	public void handleRequest(String requestType) {
		// TODO 自动生成的方法存根
		if (requestType == "加薪") {
			System.out.println(name + "批准加薪");
		} else if (leader != null) {
			leader.handleRequest(requestType);
		}
	}

}
public class ConcreteHandler_3 extends Handler {
	public ConcreteHandler_3(String name) {
		super(name);
		// TODO 自动生成的构造函数存根
	}
	@Override
	public void handleRequest(String requestType) {
		// TODO 自动生成的方法存根
		if (requestType == "分红") {
			System.out.println(name + "批准分红");
		} else if (leader != null) {
			leader.handleRequest(requestType);
		}
	}

}
③Test类

public class Test {
	public static void main(String[] args) {
		ConcreteHandler_1 ch1 = new ConcreteHandler_1("老大李明");
		ConcreteHandler_2 ch2 = new ConcreteHandler_2("经理王强");
		ConcreteHandler_3 ch3 = new ConcreteHandler_3("老板王五");
		ch1.setLeader(ch2);
		ch2.setLeader(ch3);
		ch1.handleRequest("请假");
		ch1.handleRequest("加薪");
		ch1.handleRequest("分红");
	}
}
打印结果:

老大李明批准请假
经理王强批准加薪
老板王五批准分红

(6)享元模式(Flyweight)

1.享元模式主要意图在于通过共享来支持大量的细粒度对象的使用效率
2.运用共享技术有效地支持大量细粒度的对象

①Flyweight接口

public abstract class Flyweight {
	public abstract void operation(int ex);
}
②继承类,可以是需要共享的,也可以是不需要共享的。
public class ConcreteFlyweight extends Flyweight {
	@Override
	public void operation(int ex) {
		// TODO 自动生成的方法存根
		System.out.println("具体Flyweight" + ex);
	}

}
public class UnsharedFlyweight extends Flyweight {
	@Override
	public void operation(int ex) {
		// TODO 自动生成的方法存根
		System.out.println("不共享的具体Flyweight" + ex);
	}
}
③Flyweight工厂,达到享元效果

import java.util.HashMap;
import java.util.Map;
public class FlyweightFactory {
	private Map<String, Flyweight> flyweights = new HashMap<String, Flyweight>();
	public Flyweight getFlyweight(String key) {
		if (!flyweights.containsKey(key)) // 如果此前对象已经存在则返回,否则实例一个新的对象 
			flyweights.put(key, new ConcreteFlyweight());
		return flyweights.get(key);
	}
}
④Test类

public class Test {
	public static void main(String[] args) {
		FlyweightFactory ff = new FlyweightFactory();
		Flyweight fx = ff.getFlyweight("X");
		Flyweight fx1 = ff.getFlyweight("X");
		Flyweight fx2 = ff.getFlyweight("X");
		System.out.println(fx == fx1 && fx1 == fx2); //三个对象都是同一个对象
		Flyweight fy = ff.getFlyweight("Y");
		System.out.println(fx == fy);
		UnsharedFlyweight uf = new UnsharedFlyweight();
		System.out.println(fx == uf);
	}
}

打印结果:

true
false
false


未完待续......

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值