Java设计模式,面试高频率问题,了解一下吧。参考:23种设计模式
简单工厂模式:
适用需要简单使用工厂的场景当中。
简单工厂模式属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。
模式中的角色:
工厂:简单工厂模式在类定义中已经编写好具体的实例化逻辑,对外一个父类产品的接口。
public class ProductFactory {
public static Product creator(int which){
if(which == 1)
return new Product1("P1");
else
return new Product2("P2", false);
}
}
抽象产品:该类作为接口给予用户的一个操作变量,屏蔽具体子类的实现与实例化过程
public abstract class Product {
protected String name;
protected boolean notOne = true;
public abstract String getName();
public boolean isOne(){
return notOne;
}
}
具体产品:工厂内具体实例化的产品
public class Product1 extends Product {
public Product1(String name){
this.name = name;
}
@Override
public String getName(){
return name;
}
}
public class Product2 extends Product {
public Product2(String name, boolean sss){
this.name = name;
this.notOne = sss;
}
@Override
public String getName(){
return name;
}
}
优点
工厂类是整个模式的关键,包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象。通过使用工厂类,外界可以从直接创建具体产品对象的尴尬局面摆脱出来,仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的。明确了各自的职责和权利,有利于整个软件体系结构的优化。
缺点
由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利。
工厂方法:
意图:
简单工厂方法的缺点在于工厂类需要事前知道要创建的类以及它们的创建过程,而且当需要创建的类很多的时候,所有的逻辑都放在该工厂上。而工厂方法在简单工厂模式的基础上,也使creator做成接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。
适用性:
当一个类不知道它所必须创建的对象的类的时候;当一个类希望由它的子类来指定它所创建的对象的时候;当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
工厂:
抽象出工厂的接口
public abstract class ProductFactory {
public abstract Product creator(int which);
}
其子类实现创建方法
public class ConcreteFactory extends ProductFactory {
@Override
public Product creator(int which){
if(which == 1)
return new Product1("P1");
else
return new Product2("P2", false);
}
}
如果想扩充不同的子类产品,可以使用不同的子类工厂进行生产。
抽象工厂:
意图:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 与抽象产品一样,工厂通过抽象之后,可以提供一系列产品的创建过程,每个工厂子类能生产的一系列产品都不相同。
适用性:
一个系统要独立于它的产品的创建、组合和表示时;一个系统要由多个产品系列中的一个来配置时;当你要强调一系列相关的产品对象的设计以便进行联合使用时;当你提供一个产品类库,而只想显示它们的接口而不是实现时。
抽象工厂
提供一系列产品的创建接口
public abstract class ProductsFactory {
public abstract ProductA productACreator();
public abstract ProductB productBCreator();
}
具体工厂
能具体创建一系列产品,但工厂之间生产的具体产品又不一样
public class FactoryA extends ProductsFactory {
@Override
public ProductA productACreator(){
return new ProductA1("A");
}
@Override
public ProductB productBCreator(){
return new ProductB1("A");
}
}
public class FactoryB extends ProductsFactory{
@Override
public ProductA productACreator(){
return new ProductA2("B");
}
@Override
public ProductB productBCreator(){
return new ProductB2("B");
}
}
抽象产品
提供给抽象工厂作为接口,但不具体表明产品细节
public abstract class ProductA {
protected String from;
public abstract String factoryFrom();
}
public abstract class ProductB {
protected String from;
public abstract String factoryFrom();
}
具体产品
描述产品的具体细节
public class ProductA1 extends ProductA {
public ProductA1(String from){
this.from = from;
}
@Override
public String factoryFrom(){
return "ProductA1 is from "+ from;
}
}
public class ProductA2 extends ProductA {
public ProductA2(String from){
this.from = from;
}
@Override
public String factoryFrom(){
return "ProductA2 is from "+ from;
}
}
public class ProductB1 extends ProductB {
public ProductB1(String from){
this.from = from;
}
@Override
public String factoryFrom(){
return "ProducB1 is from "+ from;
}
}
public class ProductB2 extends ProductB{
public ProductB2(String from){
this.from = from;
}
@Override
public String factoryFrom(){
return "ProductB2 is from "+ from;
}
}
建造者
建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
一个建造者掌握的技能是一样的,但具体出来的产品可能是不同的。由于建造者只拥有技能,需要一个监督来看好建造者的建造流程,保证每个产品生产流程一致。
抽象建造者
声明该类型的建造者拥有的技能
public abstract class Builder {
protected Product product;
public abstract void buildFirst();
public abstract void buildSecond();
public Product build(){
return product;
}
}
具体建造者
产品的细节因建造者的不同而有所不同
意图:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
适用性:
当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时;该对象十分复杂,不宜/不能在构造函数里马上建造出来,但能通过一些固定的步骤进行建造;当构造过程必须允许被构造的对象有不同的表示时。
public class BuilderA extends Builder{
@Override
public void buildFirst(){
product.setFirst("A");
}
@Override
public void buildSecond(){
product.setSecond("A");
}
}
public class BuilderB extends Builder {
@Override
public void buildFirst(){
product.setFirst("B");
}
@Override
public void buildSecond(){
product.setSecond("B");
}
}
监督者
指示建造者的建造过程,保证每个产品的生产步骤
public class Director {
public static void director(Builder builder){
builder.buildFirst();
builder.buildSecond();
}
}
产品
public abstract class Product {
private String first;
private String second;
public abstract String getBody();
public void setFirst(String first){
this.first = first;
}
public void setSecond(String second){
this.second = second;
}
}
单例
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统(进程)提供这个实例。使用单例的对象经常是具有资源管理器的功能,比如Android里面的Application,同一个应用如果实例多个Application,那应用就乱套。所以,选择单例模式可以避免不一致状态,在系统中只有唯一的存在。
意图:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
适用性:
当类只能有一个实例而且获取接口对全员开放;当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时(资源管理器升级,提提供更多服务)。
保护构造函数,避免外部可以通过构造函数生成实例,一般将构造函数修饰为private。
线程安全。单例模式要求只有一个实例,所以在动态生成该唯一实例时,应要避免多线程下生成多个该实例。
动态实例化
public class SingletonTest {
private SingletonTest(){}
private static SingletonTest instance = null;
public static SingletonTest getInstance(){
if(instance == null){ // 加锁前先判断,避免每次请求都加锁的性能消耗
synchronized(SingletonTest.class) {
if(instance==null) // 进入加锁区再判断,避免多个请求同时进入第一个判断的情况
instance = new SingletonTest();
}
}
return instance;
}
}
当然也可以静态实例化,无需考虑线程安全问题。
public class SingletonTest {
private SingletonTest(){}
private static SingletonTest instance = new SingletonTest();
public static SingletonTest getInstance(){
return instance;
}
}
原型
另一种不太常用的设计模式,主要在某些情况下提高创建实例的性能。
意图:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性:
当要实例化的类是在运行时刻指定时,例如,通过动态装载;或者为了避免创建一个与产品类层次平行的工厂类层次时;或者当一个类的实例只能有几个不同状态组合中的一种时;建立相应数目的原型并克隆它们可能比每次用合适的状态实例化该类更优一点。
创建原型
public class Protype implements Cloneable{
private ArrayList<String> list = new ArrayList<String>();
public Protype clone(){
Protype protype = null;
try{
protype = (Protype)super.clone(); // 浅拷贝,只拷贝基本数据类型
protype.list = (ArrayList) list.clone(); //深拷贝,显式拷贝类中的对象
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return protype;
}
}
具体原型
public class ConcreteProtype extends Protype {
private ArrayList<String> clist = new ArrayList<String>();
@Override
public ConcreteProtype clone(){
ConcreteProtype con = null;
con = (ConcreteProtype)super.clone();
con.clist = (ArrayList<String>)clist.clone();
return con;
}
}
每次想要复制该具体原型对象时,只需调用clone()方法,而无需调用构造函数。