今天我要给大家整理一下几种常用的设计模式,编程的时候可能用的不是很多,但是在面试中,设计模式一般都是必问题。掌握几种设计模式,有助于提高自己的编程思想,在面试中也是加分项。我们直接开始吧。
单例模式
- 意图:保证一个类仅有一个实例,并提供一个访问它的一个全局访问点。
- 主要解决:一个全局使用的类频繁的创建与销毁。
- 解决方案:判断系统是否已经有这个单例,有则返回,没有则创建。
- 关键代码:构造函数是私有的。
- 实现:
懒汉式:
//懒汉式-不在类加载的时候就做初始化。
public class SingletonL {
private static SingletonL instance;
private SingletonL() {
}
//可根据实际情况,是否该模式会使用在多线程中,添加synchronized关键字。
public static SingletonL getInstance() {
if (instance == null) {
instance = new SingletonL();
}
return instance;
}
}
饿汉式:
//饿汉式-类加载的时候就做初始化。
public class SingletonE {
private static SingletonE instance = new SingletonE();
private SingletonE() {
}
public static SingletonE getInstance() {
return instance;
}
}
适配器模式
- 意图:将一个类的接口转换成客户希望的另一个接口。适配器模式使原本由于接口不兼容而不能一起工作的哪些类可以一起工作。
- 主要解决:主要解决在软件系统中,常常要将一些“现存的对象”放到新的环境中,而新环境要求的接口是先对象不能满足的。
- 解决方案:继承或者依赖
- 关键代码:适配器继承或者依赖已有的对象,实现想要的目标接口。
- 实现:
//德国产的车接口 public interface DECar { void isDECar(); } //中国产的车接口 public interface CHNCar { void isCHNCar(); } //德国产的车的实现 public class DECars implements DECar { @Override public void isDECar() { System.out.println("我是在德国生产的车"); } } //适配器类 public class Adapter extends DECars implements CHNCar { @Override public void isCHNCar() { isDECar(); } } //测试类 public class Clienter { public static void main(String[] args) { CHNCar car = new Adapter(); car.isCHNCar(); } } //输出结果 我是在德国生产的车
观察者模式
- 意图:定义对象间的一种一对多的依赖关系,当一个对象状态发生改变时,所有依赖它的对象都得到通知并被自动更新。
- 主要解决:一个对象状态改变给其他对象通知问题,而且要考虑到易用和低耦合,保证高度的协作。
- 解决方案:使用面向对象的技术,可以将这种依赖关系弱化。
- 关键代码:在抽象类里有一个ArrayList存放观察者们。
- 实现:首先记住四个角色,抽象被观察者(主题)、抽象观察者、具体被观察者、具体观察者
//抽象被观察者(主题) public interface Subject { //定义三个方法,订阅、取消订阅、消息发布 public void registerSub(Observer o); public void removeSub(Observer o); public void notifySub(); } //抽象观察者 public interface Observer { public void send(String message); } //具体被观察者 实现 抽象被观察者接口 public class ISubject implements Subject { private List<Observer> list; private String message; public ISubject() { list = new ArrayList<Observer>(); } @Override public void registerSub(Observer o) { list.add(o); } @Override public void removeSub(Observer o) { if (!list.isEmpty()) { list.remove(o); } } @Override public void notifySub() { for (Observer observer : list) { observer.send(message); } } public void setInfomation(String s) { this.message = s; System.out.println("服务更新消息: " + s); // 消息更新,通知所有观察者 notifySub(); } } //具体观察者 实现 抽象观察者接口 public class IObserver implements Observer { private String name; private String message; public IObserver(String name) { this.name = name; } @Override public void send(String message) { this.message = message; read(); } public void read() { System.out.println(name + " 收到推送消息: " + message); } } //测试类 public class Clienter { public static void main(String[] args) { ISubject iSubject = new ISubject(); // 创建三个观察者 IObserver PC1 = new IObserver("PC1"); IObserver PC2 = new IObserver("PC2"); IObserver PC3 = new IObserver("PC3"); // 观察者订阅被观察主题 iSubject.registerSub(PC1); iSubject.registerSub(PC2); iSubject.registerSub(PC3); // 被观察主题发送主题消息 iSubject.setInfomation("今天放假半天"); System.out.println("----------------------"); // 有一个观察者取消观察 iSubject.removeSub(PC3); iSubject.setInfomation("明天收假"); } } //结果 服务更新消息: 今天放假半天 PC1 收到推送消息: 今天放假半天 PC2 收到推送消息: 今天放假半天 PC3 收到推送消息: 今天放假半天 ---------------------- 服务更新消息: 明天收假 PC1 收到推送消息: 明天收假 PC2 收到推送消息: 明天收假
工厂模式
- 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
- 主要解决:主要解决接口选择问题。
- 解决方案:让其子类实现工厂接口,返回的也是一个 抽象的产品。
- 关键代码:创建过程再其子类执行。
- 实现:
//抽象类/接口 public interface Car { void desc(); } //实现类一 public class Audi implements Car { @Override public void desc() { System.out.println("恭喜主人获得奥迪RS7一辆"); } } //实现类二 public class BWM implements Car { @Override public void desc() { System.out.println("恭喜主人获得宝马M4一辆"); } } //简单工厂类 public class SimpleCarFactory { public Car createCars(String model) { if("M4".equals(model)){ return new BWM(); } if("RS7".equals(model)){ return new Audi(); } return null; } } //测试类 public class Clienter { public static void main(String[] args) { SimpleCarFactory factory = new SimpleCarFactory(); Car car = factory.createCars("RS7"); car.desc(); } } //结果 恭喜主人获得奥迪RS7一辆
抽象工厂模式
- 意图:提供一个创建一系列相关或相互依赖对象的接口,而无需制定它们具体的类。
- 主要解决:主要解决接口选择问题。
- 解决方案:在一个产品族里,定义多个产品。
- 关键代码:在一个工厂里聚合多个同类产品。
- 实现:
//先建立两个工厂模式 //抽象类一 public interface CHNShape { void desc(); } //实现类一 public class CHNAudi implements CHNShape { @Override public void desc() { System.out.println("我是中国生产的奥迪RS7"); } } //抽象类二 public interface DEShape { void desc(); } //实现类二 public class DEAudi implements DEShape { @Override public void desc() { System.out.println("我是德国生产的奥迪RS7"); } } //创建一个抽象类 public abstract class AbstractCarFactory { abstract CHNShape getCHNShape(String type); abstract DEShape getDEShape(String type); } //对简单工厂进行改写,继承抽象类 中国工厂只生产中国的车 public class CHNShapeFactory extends AbstractCarFactory{ @Override CHNShape getCHNShape(String type) { if("RS7".equals(type)){ return new CHNAudi(); } return null; } @Override DEShape getDEShape(String type) { // TODO Auto-generated method stub return null; } } //对简单工厂进行改写,继承抽象类 德国工厂只生产的德国的车 public class DEShapeFactory extends AbstractCarFactory{ @Override CHNShape getCHNShape(String type) { // TODO Auto-generated method stub return null; } @Override DEShape getDEShape(String type) { if("RS7".equals(type)){ return new DEAudi(); } return null; } } //建立超级工厂类 public class SuperShapeFactory { public AbstractCarFactory getFactory(String factoryType) { if ("CHN".equals(factoryType)) { return new CHNShapeFactory(); } if ("DE".equals(factoryType)) { return new DEShapeFactory(); } return null; } } //测试类 public class Clienter { public static void main(String[] args) { SuperShapeFactory superShapeFactory = new SuperShapeFactory(); AbstractCarFactory factory = superShapeFactory.getFactory("CHN"); factory.getCHNShape("RS7").desc();; System.out.println("---------------------------"); AbstractCarFactory factory1 = superShapeFactory.getFactory("DE"); factory1.getDEShape("RS7").desc(); } } //结果 我是中国生产的奥迪RS7 --------------------------- 我是德国生产的奥迪RS7
装饰器模式:
- 意图:动态的给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更加灵活。
- 主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
- 解决方案:将具体功能职责划分,同时继承装饰者模式
- 关键代码:1、Component类充当抽象角色,不应该具体实现。2、修饰类引用和继承Componentl类,具体扩展类重写父类方法。
- 实现:
//接口 public interface Car { void desc(); } //实现类 public class Audi implements Car { @Override public void desc() { System.out.println("我是奥迪RS7"); } } //抽象装饰类 public abstract class CarDescorator implements Car { protected Car descoratorCar; public CarDescorator(Car descoratorCar) { this.descoratorCar = descoratorCar; } @Override public void desc() { descoratorCar.desc(); } } //实体装饰类 public class RedCarDescorator extends CarDescorator { public RedCarDescorator(Car descoratorCar) { super(descoratorCar); } @Override public void desc() { super.desc(); setRedBorder(descoratorCar); } private void setRedBorder(Car decoratedCar) { System.out.println("红色的"); } } //测试类 public class Clienter { public static void main(String[] args) { Car audi = new Audi(); RedCarDescorator redCarDescorator = new RedCarDescorator(audi); redCarDescorator.desc(); } } //结果 我是奥迪RS7 红色的