本篇文章,我们来看看java常用的设计模式。
1.单例模式
单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。优点是整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体,并且减少开销。有懒汉式和饿汉式两种。
//饿汉式
public class Singleton{
private static Singleton singleton = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return singleton;
}
}
//懒汉式
class Single {
private Single() { }
// 延迟加载
private static Single s = null;
public static Single getInstance() {
//双重判断提高效率,后来的就不需要再判断锁内的内容,如果不符合条件就直接return
if (null == s)
{
//同步代码块,该处的锁是这个类的字节码对象
synchronized (Single.class)
{
if (null == s) {
s = new Single();
}
}
}
return s;
}
}
2.工厂模式
工厂模式为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。分为三类
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
/**
* 简单工厂模式,有三个组成
* 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。
* 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
* 具体产品角色:工厂类所创建的对象就是此角色的实例。
**/
public class Factory{
public static Sample creator(int which){
if (which==1)
return new SampleA();
else if (which==2)
return new SampleB();
}
}
/**
* 工厂方法模式
* 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。
* 具体工厂角色:它含有和具体业务逻辑有关的代码。由
* 抽象产品角色:它是具体产品继承的父类或者是实现的接口。
* 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
**/
//抽象产品角色
public interface Moveable {
void run();
}
//具体产品角色
public class Plane implements Moveable {
@Override
public void run() {
System.out.println("plane....");
}
}
//具体产品角色
public class Broom implements Moveable {
@Override
public void run() {
System.out.println("broom.....");
}
}
//抽象工厂
public abstract class VehicleFactory {
abstract Moveable create();
}
//具体工厂
public class PlaneFactory extends VehicleFactory{
public Moveable create() {
return new Plane();
}
}
//具体工厂
public class BroomFactory extends VehicleFactory{
public Moveable create() {
return new Broom();
}
}
//测试类
public class Test {
public static void main(String[] args) {
VehicleFactory factory = new BroomFactory();
Moveable m = factory.create();
m.run();
}
}
工厂方法模式使用继承自抽象工厂角色的多个子类来代替简单工厂模式中的“上帝类”。正如上面所说,这样便分担了对象承受的压力;而且这样使得结构变得灵活 起来——当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代 码。可以看出工厂角色的结构也是符合开闭原则的!
/**
* 抽象工厂模式
**/
//抽象工厂类
public abstract class AbstractFactory {
public abstract Vehicle createVehicle();
public abstract Weapon createWeapon();
public abstract Food createFood();
}
//具体工厂类,其中Food,Vehicle,Weapon是抽象类,
public class DefaultFactory extends AbstractFactory{
@Override
public Food createFood() {
return new Apple();
}
@Override
public Vehicle createVehicle() {
return new Car();
}
@Override
public Weapon createWeapon() {
return new AK47();
}
}
//测试类
public class Test {
public static void main(String[] args) {
AbstractFactory f = new DefaultFactory();
Vehicle v = f.createVehicle();
v.run();
Weapon w = f.createWeapon();
w.shoot();
Food a = f.createFood();
a.printName();
}
}
在抽象工厂模式中,抽象产品 (AbstractProduct) 可能是一个或多个,从而构成一个或多个产品族(Product Family)。 在只有一个产品族的情况下,抽象工厂模式实际上退化到工厂方法模式。
3.建造者(Builder)模式
建造模式是一种对象构建的设计模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们。用户不知道内部的具体构建细节。Builder模式是非常类似抽象工厂模式,细微的区别大概只有在反复使用中才能体会到。
我们先定义一个对象
public class Car {
// 尺寸
private String size;
// 方向盘
private String steeringWheel;
// 底座
private String pedestal;
// 轮胎
private String wheel;
// 排量
private String displacement;
......
然后定义建造者对象
public class CarBuilder {
// 车型
private String type;
// 动力
private String power;
// 舒适性
private String comfort;
public Car build() {
return new Car(this);
}
........
build方法是建造者模式好像约定俗成的方法名,代表建造,里面把自身对象传给Car,这个构造方法的实现我在第一段代码里面是没有贴的,这段代码的实现为:
public Car(CarBuilder builder) {
if ("紧凑型车".equals(builder.getType())) {
this.size = "大小--紧凑型车";
} else if ("中型车".equals(builder.getType())) {
this.size = "大小--中型车";
} else {
this.size = "大小--其他";
}
if ("很舒适".equals(builder.getComfort())) {
this.steeringWheel = "方向盘--很舒适";
this.pedestal = "底座--很舒适";
} else if ("一般舒适".equals(builder.getComfort())) {
this.steeringWheel = "方向盘--一般舒适";
this.pedestal = "底座--一般舒适";
} else {
this.steeringWheel = "方向盘--其他";
this.pedestal = "底座--其他";
}
if ("动力强劲".equals(builder.getPower())) {
this.displacement = "排量--动力强劲";
this.maxSpeed = "最大速度--动力强劲";
this.steeringWheel = "轮胎--动力强劲";
} else if ("动力一般".equals(builder.getPower())) {
this.displacement = "排量--动力一般";
this.maxSpeed = "最大速度--动力一般";
this.steeringWheel = "轮胎--动力一般";
} else {
this.displacement = "排量--其他";
this.maxSpeed = "最大速度--其他";
this.steeringWheel = "轮胎--其他";
}
}
然后我们来真实构建一下
public void test() {
Car car = new CarBuilder().comfort("很舒适").power("动力一般").type("紧凑型车").build();
System.out.println(JSON.toJSONString(car));
}
构造者模式的好处是无论多复杂的逻辑都在这里实现而不需要暴露给开发者,总结就是:实现了对象的属性与构建的分离。
很多开源框架中都用到了构建者模式,比如mybatis等,会用到SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);等。
4.观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。观察者模式又叫发布-订阅(Publish/Subscribe)模式。
观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,都有这种模式的影子,比如,邮件订阅、RSS Feeds,本质上都是观察者模式。这里就不写代码具体实现了,
5.适配器模式
适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
代码示例:
public interface Target {
/**
* 这是源类Adaptee也有的方法
*/
public void sampleOperation1();
/**
* 这是源类Adapteee没有的方法
*/
public void sampleOperation2();
}
public class Adapte {
public void sampleOperation1(){}
}
适配器类:
public class Adapter {
private Adaptee adaptee;
public Adapter(Adaptee adaptee){
this.adaptee = adaptee;
}
/**
* 源类Adaptee有方法sampleOperation1
* 因此适配器类直接委派即可
*/
public void sampleOperation1(){
this.adaptee.sampleOperation1();
}
/**
* 源类Adaptee没有方法sampleOperation2
* 因此由适配器类需要补充此方法
*/
public void sampleOperation2(){
//写相关的代码
}
}
适配器模式的优点是有更好的复用性和扩展性,过多的使用适配器,会让系统非常零乱,不易整体进行把握,因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。
6.代理模式
代理模式是为其他对象提供一种代理以控制对这个对象的访问。也可以说,在出发点到目的地之间有一道中间层,意为代理。优点是在不更改对象的情况下,可以额外做很多事情,代理模式在spring中应用非常广泛,包括aop都是基于代理实现的,这里就不详细举例了。
网友评论