设计模式是为了让程序有更好的:java
对类来讲,即一个类只负责一项职责。如类A负责两个不一样职责:职责1和职责2。当职责1需求变动而改变A时,也有可能致使职责2执行错误,所以须要把类A的粒度分解为A1与A2。android
客户端不该该依赖它不须要的接口,即一个类对另外一个类的依赖应该创建在最小的接口上。接口尽可能细化,同时接口中的方法尽可能少。ios
经过抽象(接口或者抽象类)使各个类或模块的实现彼此独立,不相互影响,实现模块间的松耦合。程序员
面向接口编程算法
父类能出现的地方子类就能够出现,并且替换成子类也不会出现任何错误或者异常,而使用者也无需知道父类仍是子类。数据库
软件实体(包括类、模块、功能等)应该对扩展开放,可是对修改关闭。编程
UML--Unified modeling language(统一建模语言),是一种用于软件系统分析和设计的语言工具,它用于帮助软件开发人员进行思考和思路的结果。 ####UML类图分类设计模式
所谓类的单例设计模式,就是采起必定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,而且该类只提供一个取得其对象实例的方法(静态方法)。安全
class Singleton {
private Singleton() {
}
private static final Singleton singleton = new Singleton();
public static Singleton getInstance() {
return singleton;
}
}
复制代码
这种写法比较简单,就是在类装载的时候就完成实例化,避免了线程同步的问题。多线程
在类加载的时候就完成了实例化,没有达到懒加载的效果。若是从始至终都没有用过这个实例,则会形成内存的浪费。
这种单例设计模式可用,可是可能会出现内存浪费。
class Singleton {
private Singleton() {
}
private static Singleton singleton;
static {
singleton = new Singleton();
}
public static Singleton getInstance() {
return singleton;
}
}
复制代码
与饿汉式(静态常量)的方式相似,只不过将类实例化的过程放在了静态代码块中,优缺点与饿汉式(静态常量)同样。
class Singleton {
private Singleton() {
}
private static Singleton singleton;
/** * 当调用的时候再建立对象,可是线程不安全。好比线程1执行到singleton为空,此时线程2也执行到此为止,而后就会产生两个对象。 * @return */
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
复制代码
if (singleton == null)
判断语句块,还将来得及往下执行,另外一个线程也经过了这个判断语句,这是便会产生多个实例。所以在多线程的环境下不可使用这个方式。class Singleton {
private Singleton() {
}
private static Singleton singleton;
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
复制代码
class Singleton {
private Singleton() {
}
//为了不初始化操做的指令重排序
private static volatile Singleton singleton;
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
复制代码
class Singleton {
private Singleton() {
}
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
复制代码
enum Singleton{
INSTANCE;
}
复制代码
java.lang.Runtime就是经典的单例模式(饿汉式),代码以下:
private static Runtime currentRuntime = new Runtime();
/** * Returns the runtime object associated with the current Java application. * Most of the methods of class <code>Runtime</code> are instance * methods and must be invoked with respect to the current runtime object. * * @return the <code>Runtime</code> object associated with the current * Java application. */
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}
复制代码
经过举个例子说明一下: 我喜欢养宠物,抽象一个宠物父类或者接口。
/** * 描述要养的宠物 * * @author bf * @date 2019/9/18 17:01 */
public interface Animal {
void getAnimal();
}
复制代码
先养一个小狗吧:
public class Dog implements Animal {
@Override
public void getAnimal() {
System.out.println("养了一只小狗");
}
}
复制代码
再养一只小猫:
public class Cat implements Animal {
@Override
public void getAnimal() {
System.out.println("养了一只小猫");
}
}
复制代码
再养一只竹鼠:
public class Mouse implements Animal {
@Override
public void getAnimal() {
System.out.println("养一只竹鼠");
}
}
复制代码
准备工做完成了,咱们去宠物馆(简单工厂类),宠物种类以下:
public class SimpleAnimalFactory {
private static final int TYPE_DOG = 1;
private static final int TYPE_CAT = 2;
private static final int TYPE_MOUSE = 3;
public static Animal createAnimals(int type) {
switch (type) {
case TYPE_DOG:
return new Dog();
case TYPE_CAT:
return new Cat();
case TYPE_MOUSE:
return new Mouse();
default:
return null;
}
}
}
复制代码
简单宠物馆就提供三种动物,你说要什么,他就给你什么。这里我要了一只狗:
public static void main(String[] args) {
Animal animals = SimpleAnimalFactory.createAnimals(1);
animals.getAnimal();
}
复制代码
输出以下:
养了一只小狗
使用反射实现简单工厂:
public static <T> T createAnimals(Class<T> clz) throws Exception {
T result = null;
result = (T) Class.forName(clz.getName()).newInstance();
return result;
}
复制代码
买宠物时调用:
Dog dog = SimpleReflectAnimalFactory.createAnimals(Dog.class);
dog.getAnimal();
复制代码
工厂方法模式是简单工厂的进一步深化,在工厂方法模式中,咱们再也不提供一个统一的工厂类来建立全部的对象,而是针对不一样的对象提供不一样的工厂。也就是说每个对象都有一个与之对应的工厂。
定义一个用于建立对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
咱们能够先经过实例来详细解释一下这个定义:
依然使用养宠物的例子: 首先,编写一个宠物接口:
public interface Animal {
void getAnimal();
}
复制代码
养狗的代码:
public class Dog implements Animal {
@Override
public void getAnimal() {
System.out.println("养了一只小狗");
}
}
复制代码
养猫的代码:
public class Cat implements Animal {
@Override
public void getAnimal() {
System.out.println("养了一只小猫");
}
}
复制代码
养竹鼠的代码:
public class Mouse implements Animal {
@Override
public void getAnimal() {
System.out.println("养一只竹鼠");
}
}
复制代码
如今咱们按照定义所说定义一个抽象的工厂接口GetAnimalFactory
public interface GetAnimalFactory {
Animal getAnimal();
}
复制代码
Dog加载器工厂
public interface GetAnimalFactory {
Animal getAnimal();
}
复制代码
Cat加载器工厂
public class GetCat implements GetAnimalFactory {
@Override
public Animal getAnimal() {
return new Cat();
}
}
复制代码
Mouse加载器工厂
public class GetMouse implements GetAnimalFactory {
@Override
public Animal getAnimal() {
return new Mouse();
}
}
复制代码
和简单工厂对比一下,最根本的区别在于简单工厂只有一个统一的工厂类,而工厂方法是针对每一个要建立的对象都会提供一个工厂类。
提供一个建立一系列相关或相互依赖对象的接口,而无需指定它们具体的类。(在抽象工厂模式中,每个具体工厂都提供了多个工厂方法用于产生多种不一样类型的对象) 抽象工厂能够划 分为4大部分:
如今须要作一款跨平台的游戏,须要兼容Android和Ios两个移动操做系统,该游戏针对每一个系统都设计了一套操做控制器(OperationController)和界面控制器(UIController),下面经过抽象工厂方式完成这款游戏的架构设计。 先建立两个抽象产品接口。
抽象操做控制器
public interface OperationController {
void control();
}
复制代码
抽象界面控制器
public interface UIController {
void display();
}
复制代码
而后完成这两个系统平台的具体操做控制器和界面控制器
Android平台
public class AndroidOperationController implements OperationController {
@Override
public void control() {
System.out.println("AndroidOperationController");
}
}
复制代码
public class AndroidUIController implements UIController {
@Override
public void display() {
System.out.println("AndroidUIController");
}
}
复制代码
Ios
public class IosOperationController implements OperationController {
@Override
public void control() {
System.out.println("IosOperationController");
}
}
复制代码
public class IosUIController implements UIController {
@Override
public void display() {
System.out.println("IosUIController");
}
}
复制代码
下面定义一个抽象工厂,该工厂能够建立OperationController和UIController
public interface SystemFactory {
OperationController createOperationController();
UIController createUIController();
}
复制代码
而后在各平台具体的工厂类中完成操做控制器和界面控制器的建立过程
Android
public class AndroidFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new AndroidOperationController();
}
@Override
public UIController createUIController() {
return new AndroidUIController();
}
}
复制代码
Ios
public class IOSFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new IosOperationController();
}
@Override
public UIController createUIController() {
return new IosUIController();
}
}
复制代码
方法调用:
public static void main(String[] args) {
//android
AndroidFactory androidFactory = new AndroidFactory();
OperationController androidOperationController = androidFactory.createOperationController();
UIController androidUiController = androidFactory.createUIController();
androidOperationController.control();
androidUiController.display();
//ios
IOSFactory iosFactory = new IOSFactory();
OperationController iosFactoryOperation = iosFactory.createOperationController();
UIController iosUiController = iosFactory.createUIController();
iosFactoryOperation.control();
iosUiController.display();
}
复制代码
针对不一样平台只经过建立不一样的工厂对象就完成了操做和UI控制器的建立。
定义一个操做中的算法的框架,而将一些步骤延迟到子类中。使得子类能够不改变一个算法的结构便可从新定义该算法的某些特定步骤。
举个骑共享单车的例子,无论是骑哈罗单车仍是骑摩拜单车,咱们都要经历扫码解锁、骑车、上锁、支付这四个过程,所以能够设计成一个抽象方法。
public abstract class RideBike {
/** * 扫码解锁 */
public abstract void unlock();
/** * 骑车 */
public abstract void ride();
/** * 上锁 */
public abstract void lock();
/** * 支付 */
public abstract void pay();
/** * 模拟使用共享单车 */
public abstract void use();
}
复制代码
上班去了,开始去骑共享单车,发现了一辆哈罗单车,开始使用。
public class RideHelloBike extends RideBike {
@Override
public void unlock() {
System.out.println("扫码解锁哈罗单车");
}
@Override
public void ride() {
System.out.println("开启骑哈罗单车");
}
@Override
public void lock() {
System.out.println("给哈罗单车上锁");
}
@Override
public void pay() {
System.out.println("支付哈罗单车的费用");
}
@Override
public void use() {
this.unlock();
this.ride();
this.ride();
this.pay();
}
}
复制代码
终于下班了,发现公司楼下的哈罗单车都被骑完了,那就骑摩拜单车吧。
public class RideMoBaiBike extends RideBike {
@Override
public void unlock() {
System.out.println("扫码解锁摩拜单车");
}
@Override
public void ride() {
System.out.println("开启骑摩拜单车");
}
@Override
public void lock() {
System.out.println("给摩拜单车上锁");
}
@Override
public void pay() {
System.out.println("支付摩拜单车的费用");
}
@Override
public void use() {
this.unlock();
this.ride();
this.ride();
this.pay();
}
}
复制代码
骑摩拜和骑哈罗都用到了一样的方法,user()方法,代码重复了,这是病得治,药房就是使用模板方法模式。
模板方法模式相信你们都用过,就是抽象类里面的方法,不须要改变的方法。那么,下面咱们开始编写代码。
抽象类代码
public abstract class AbstractClass {
protected abstract void unlock();
protected abstract void ride();
protected abstract void lock();
protected abstract void pay();
protected final void use() {
this.unlock();
this.ride();
this.lock();
this.pay();
}
}
复制代码
这里说明一下:使用protected,只有同包下的父子类能够访问。 final修饰的方法代表子类不能重写父类方法。
实现类代码
public class ScanBicycle extends AbstractClass {
@Override
protected void unlock() {
System.out.println("扫码解锁");
}
@Override
protected void ride() {
System.out.println("骑车");
}
@Override
protected void lock() {
System.out.println("上锁");
}
@Override
protected void pay() {
System.out.println("支付");
}
public static void main(String[] args) {
ScanBicycle bicycle = new ScanBicycle();
bicycle.use();
}
}
复制代码
运行结果以下:
public class ScanBicycle extends AbstractClass {
@Override
protected void unlock() {
System.out.println("扫码解锁哈罗单车");
}
@Override
protected void ride() {
System.out.println("骑哈罗车");
}
@Override
protected void lock() {
System.out.println("上哈罗锁");
}
@Override
protected void pay() {
System.out.println("支付哈罗费用");
}
public static void main(String[] args) {
ScanBicycle bicycle = new ScanBicycle();
bicycle.use();
}
}
复制代码
模板方法看上去简单,可是整个模式涉及到的都是面向对象设计的核心,好比继承封装、基于继承代码的复用、方法实现等等。当中还有涉及到一些关键词的使用,也是咱们在Java编程中须要掌握的基础。