评判一个程序员是否优秀,就是 show me the code。优秀的代码可读性强,高内聚低耦合,可扩展。想要写优秀的代码,作个优秀的程序员,就须要多看看大牛写的开源框架,吸收其中的精华,多学学设计模式,除此以外,没有任何其余捷径。java
设计模式主要分为建立型模式、结构型模式、行为型模式三种类型。程序员
定义一个建立对象的接口,让实现这个接口的类来决定实例化哪一个类。工厂方法让类的实例化推迟到子类中进行,它属于建立型模式。编程
工厂对象一般包含一个或多个方法,用来建立这个工厂所能建立的各类类型的对象。这些方法可能接收参数,用来指定对象建立的方式,最后返回建立的对象。设计模式
工厂一般是一个用来建立其余对象的对象。工厂是构造方法的抽象,用来实现不一样的分配方案。数组
维基百科工厂方法的例子bash
// 定义了 Button 如何建立
public interface Button{}
// 实现了 WinButton
public class WinButton implements Button{}
// 实现了 MacButton
public class MacButton implements Button{}
// 建立 Button 的工厂类
public interface ButtonFactory {
Button createButton();
}
// 真正建立 WinButton 的实现类,实现了 ButtonFactory
public class WinButtonFactory implements ButtonFactory {
@Override
public static Button createButton(){
return new WinButton();
}
}
// 真正建立 MacButton的实现类,实现了 ButtonFactory
public class MacButtonFactory implements ButtonFactory {
@Override
public static Button createButton(){
return new MacButton();
}
}
复制代码
将一组具备同一主题的单独的工厂封装起来。在使用中,使用方须要建立抽象工厂的具体实现,而后使用抽象工厂做为接口来建立这一方法的具体对象。它属于建立型模式。微信
抽象工厂就好像是对工厂方法的一种扩展,有个产品族的概念,也就是一堆产品。上面的工厂方法就一个产品(Button),而下面抽象工厂的例子里有两个产品(Button和 Border)。app
抽象工厂的优势:
具体产品从客户代码中被分离出来。
容易改变产品的系列。
将一个系列的产品族统一到一块儿建立。框架
抽象工厂的缺点:
在产品族中扩展新的产品是很困难的,它须要修改抽象工厂的接口。ide
维基百科抽象工厂的例子
public interface Button {}
public interface Border {}
public class WinButton implements Button {}
public class WinBorder implements Border {}
public class MacButton implements Button {}
public class MacBorder implements Border {}
public interface AbstractFactory {
Button createButton();
Border createBorder();
}
public class WinFactory {
@Override
public static Button createButton() {
return new WinButton();
}
@Override
public static Border createBorder() {
return new WinBorder();
}
}
public class MacFactory {
@Override
public static Button createButton() {
return new MacButton();
}
@Override
public static Border createBorder() {
return new MacBorder();
}
}
复制代码
当构建一个复杂对象时,就可使用建造者模式。它实际上就是传入一个参数,而后返回对象自己,方便下一个属性或者参数来构建。能够按需构建对象,可扩展性强。它属于建立型模式。
在 JDK 中,StringBuilder 类的 append() 方法就是一个很好的构建模式例子。
// java.lang.StringBuilder
@Override
public StringBuilder append(CharSequence s) {
super.append(s);
return this;
}
复制代码
它的特色在于经过 复制 一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是咱们所称的原型,这个原型是可定制的。它属于建立型模式。
原型模式多用于建立复杂的或者耗时的实例,由于这种状况下,复制一个已经存在的实例使程序运行更高效,它们实际上就是命名不同的同类数据。
在 JDK 中,Object 类中的 clone() 方法就是典型的原型模式。
//在具体的实现类里能够直接重写 clone() 方法
protected native Object clone() throws CloneNotSupportedException;
复制代码
无论在任什么时候候,获取一个对象时只会返回同一个实例。一般咱们在都读取配置文件时,文件里的内容是不变的,所以咱们就可使用单例模式来实现。它属于建立型模式。
单例模式很简单,只须要三步就完成,下面是 JDK 里的 Runtime 类实现的单例模式。
public class Runtime {
// 1.new 一个私有的静态的 Runtime 实例
private static Runtime currentRuntime = new Runtime();
// 2.返回当前应用的 Runtime 实例
public static Runtime getRuntime() {
return currentRuntime;
}
// 3.私有化构造方法,不容许在其它类构造 Runtime 实例
private Runtime() {}
}
复制代码
适配器模式也称做包装(wrapper),它属于结构型模式。
它的做用是把本来两个不兼容的接口经过一个适配器或者包装成兼容的接口,而后它们能够一块儿工做。例如咱们的手机数据线,就比如是一个适配器,一端是 USB接口,一端是 Type-C 或者 Lightning 接口,原本它们是不能一块儿工做的,但咱们用这跟数据线(适配器)就可让它们协同工做了。
它的优势:
1.可让任何两个没有关联的接口一块儿工做。
2.提升了接口的复用。
3.增长了接口的透明度。
4.灵活性好。
它的缺点:
1.过多地使用适配器,会让系统很是零乱,不易总体进行把握。
2.因为 JAVA 只能继承一个类,因此最多只能适配一个适配者类,并且目标类必须是抽象类。
在 JDK 中,Arrays 类中的 asList(T... a) 方法就是适配器模式的例子,把一个数组转换为一个集合。
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
复制代码
在 JDK 中,Collections 工具类的 list() 方法把枚举转集合。
public static <T> ArrayList<T> list(Enumeration<T> e) {
ArrayList<T> l = new ArrayList<>();
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
复制代码
固然,这上面两个例子是很是简单的,好像看不出来使用了任何的设计模式,跟咱们平时使用的转换如出一辙。这里只是一个理念的介绍,实际上,在使用中是用一个中间的 Adapter 类来作兼容或者包装的。
将抽象与其实现分离,以便二者能够独立变化。它属于结构型模式。
当一个类常常变化时,面向对象编程的特性变得很是有用,由于能够用最少的关于程序的先验知识来容易地改变程序的代码。当类和它常常变化时,桥模式颇有用。类自己能够被认为是抽象,类能够做为实现来作。桥模式也能够被认为是两层抽象。
它经过提供抽象化和实现化之间的桥接结构,来实现两者的解耦。
它的优势:
1.抽象和实现分离开。
2.优秀的扩展能力。
3.实现细节对调用方透明。
它的缺点:
桥接模式的引入会增长系统的理解与设计难度,因为聚合关联关系创建在抽象层,须要针对抽象进行设计与编程,加深编程难度。
这是个生产不一样车辆和须要不一样生产流程的例子。首先,定义一个车辆(Vehicle)的抽象接口,里面有个生产车辆的对应流程集合和一个生产的抽象方法。而后是自行车(Bike)和汽车(Car)对抽象接口的实现。而后定义一个生产车辆须要的流程(WorkShop),它有两个实现 ProduceWorkShop 和 TestWorkShop。最后,main 方法的代码就是对这个桥接模式的使用方式。
这种设计模式的好处是方便添加一种车巴士(Bus),只须要继承 Vehicle 类。也很是方便的添加一种生产流程喷漆(PaintWorkShop),只须要继承 WorkShop 类便可,扩展性很高。
//车辆的抽象接口
public abstract class Vehicle {
//
protected List<WorkShop> workshops = new ArrayList<WorkShop>();
public Vehicle() {
super();
}
public boolean joinWorkshop(WorkShop workshop) {
return workshops.add(workshop);
}
public abstract void manufacture();
}
//自行车的实现
public class Bike extends Vehicle {
@Override
public void manufacture() {
System.out.println("Manufactoring Bike...");
workshops.stream().forEach(workshop -> workshop.work(this));
}
}
//汽车的实现
public class Car extends Vehicle {
@Override
public void manufacture() {
System.out.println("Manufactoring Car");
workshops.stream().forEach(workshop -> workshop.work(this));
}
}
//生产车的抽象接口
public abstract class WorkShop {
public abstract void work(Vehicle vehicle);
}
//制造车的实现
public class ProduceWorkShop extends WorkShop {
public ProduceWorkShop() {
super();
}
@Override
public void work(Vehicle vehicle) {
System.out.print("Producing... ");
}
}
//测试车的实现
public class TestWorkShop extends WorkShop {
public TestWorkShop() {
super();
}
@Override
public void work(Vehicle vehicle) {
System.out.print("Testing... ");
}
}
//使用
public class Main {
public static void main(String[] args) {
//生产一辆自行车
Vehicle bike = new Bike();
bike.joinWorkshop(new ProduceWorkShop());
bike.manufacture();
//生产一辆汽车
Vehicle car = new Car();
car.joinWorkshop(new ProduceWorkShop());
car.joinWorkshop(new TestWorkShop());
car.manufacture();
}
}
复制代码
最后,单看设计模式例子是很是简单的,但有时候写代码时却用不上这些设计模式,这是一种写代码思惟上的转变。也就是在写代码以前,咱们须要根据业务场景思考,那种设计模式适合使用,记住使用设计模式的最终目的是代码可读性强,高内聚低耦合,可扩展。这是一种思惟上的转变,多思考在动手,熟能生巧。
PS:
清山绿水始于尘,博学多识贵于勤。
微信公众号:「清尘闲聊」。
欢迎一块儿谈天说地,聊代码。