软件设计模式
软件设计模式
简介
软件工程中,设计模式(Design Pattern)是对软件设计中普遍存在的各种问题,所提出的解决方案。是从建筑设计领域引入计算机科学的。设计模式是为了让软件具有更好的代码重用性、可读性、可扩展性、可靠性。
UML图
UML简介
UML(Unified Modeling Language)是统一建模语言。是一种用于软件系统分析和设计的语言工具,它用于帮助软件开发人员进行思考和记录思路的结果。其本身是一套符号的规定,就像数学符号和化学符号一样。这些符号用于描述软件模型中的各个元素和他们之间的关系,比如类、接口、实现、泛化、依赖、组合、聚合等。UML建模工具常用有Rational Rose,也可以使用一些插件来建模。
UML分类
分为用例图、静态结构图、动态行为图。
用例图
静态结构图:类图、对象图、包图、组件图、部署图
动态行为图:交互图、状态图、活动图
UML类图
用于描述系统中类本身的组成和类之间的各种静态关系。
类之间的关系:依赖、泛化、实现、关联、聚合、组合
依赖:只要是在类中用到了对方,则就存在依赖关系。使用方指向依赖方。
泛化:泛化实际就是继承,是依赖关系的一种。子类指向父类
实现:实现接口就是实现关系,是依赖关系的一种。由实现方指向接口方。
关联:类与类之间的联系,是依赖关系的一种。具有导航性,即双向关系或单向关系。A类用到了B类则由A指向B是单向关系。如果B类也用到了A类,则B类也要指向A类是双向关系。
聚合:表示整体和部分的关系,整体和部分可以分开,聚合关系是关联关系的特例。具有关联的导航性与多重性。A类使用到了B类,则空心菱形指向A类。
组合:表示整体和部分的关系,整体和部分不可以分开。比如A类使用了B类,A类消失B类也消失则说明其不能分开是组合关系。这种情况一般是A类中有一个B类的属性,并且直接new出来了一个B类对象。实心菱形指向A类。

类图画法
package com.tensoflow;
public class Person {
private Integer id;
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

七大原则
设计模式原则,是程序员在编程时应当遵守的原则。也是各种设计模式的基础,是设计模式为什么这样设计的依据。
单一职责原则
对类来说一个类应该只负责一项职责。如果A类负责职责1、职责2两个不同的职责当职责1需求变更而改变A时,可能造成职责2执行错误。此时应将A类分成两份分别负责职责1和职责2。
package com.tensoflow.principle.singleResponsibility.problem;
class Vehicle {
public void run(String vehicle) {
System.out.println(vehicle + " 在公路上运行...");
}
}
/*
Vehicle交通工具类: run()方法违反了单一职责原则
解决方案: 应该根据交通工具运行方法不同,分解成不同的类
*/
public class SingleResponsibility {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.run("摩托车");
vehicle.run("汽车");
// 飞机不能在公路上运行
vehicle.run("飞机");
}
}
package com.tensoflow.principle.singleResponsibility.improve0;
class RoadVehicle {
public void run(String vehicle) {
System.out.println(vehicle + " 在公路上运行...");
}
}
class AirVehicle {
public void run(String vehicle) {
System.out.println(vehicle + " 在天空上运行...");
}
}
class WaterVehicle {
public void run(String vehicle) {
System.out.println(vehicle + " 在水上运行...");
}
}
/*
此种方式遵循了单一职责原则
弊端: 这种方式的改动很大,要将类分解,同时要修改客户端
改进: 直接修改Vehicle类,改动的代码会比较少
*/
public class SingleResponsibility {
public static void main(String[] args) {
RoadVehicle roadVehicle = new RoadVehicle();
roadVehicle.run("摩托车");
AirVehicle airVehicle = new AirVehicle();
airVehicle.run("飞机");
WaterVehicle waterVehicle = new WaterVehicle();
waterVehicle.run("轮船");
}
}
package com.tensoflow.principle.singleResponsibility.improve1;
class Vehicle {
public void runRoad(String vehicle) {
System.out.println(vehicle + " 在公路上运行...");
}
public void runAir(String vehicle) {
System.out.println(vehicle + " 在天空上运行...");
}
public void runWater(String vehicle) {
System.out.println(vehicle + " 在水上运行...");
}
}
/*
此方式没有对原本类做大的修改,只是增加方法
此方式虽然没有在类上遵守单一职责原则,但是在方法级别上仍遵守单一职责原则
*/
public class SingleResponsibility {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.runRoad("摩托车");
vehicle.runAir("飞机");
vehicle.runWater("轮船");
}
}
通常情况下,我们应当遵守单一职责原则。只有逻辑足够简单时才可以在代码级别违反单一职责原则。只有类中方法数量足够少时才可以在方法级别上保持单一职责原则。
迪米特法则
一个对象应该对其它对象保持最少的了解。类与类关系越密切,耦合度越大。迪米特法则又叫最少知道原则。即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的public方法,不对外泄露任何信息。
package com.tensoflow.principle.demeter.problem;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
// 学校总部员工类
@Data
class Employee {
private String id;
}
// 学院员工类
@Data
class CollegeEmployee {
private String id;
}
// 管理学院员工的管理类
class CollegeManagement {
public List<CollegeEmployee> getAllEmployee() {
List<CollegeEmployee> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
CollegeEmployee emp = new CollegeEmployee();
emp.setId("学院员工Id = " + i);
list.add(emp);
}
return list;
}
}
/*
管理学校总部员工的管理类
SchoolManagement的直接朋友:Employee、CollegeManagement
SchoolManagement的间接朋友:CollegeEmployee 这样违背了迪米特法则
*/
class SchoolManagement {
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setId("学校总部员工Id = " + i);
list.add(emp);
}
return list;
}
// 输出学校总部和学院员工信息的方法
void printAllEmployee(CollegeManagement sub) {
// 输出学院员工信息的代码不应该写在学校管理类中,应写到管理学院的类中
List<CollegeEmployee> list1 = sub.getAllEmployee();
System.out.println("--------------分公司员工--------------");
for(CollegeEmployee e : list1) {
System.out.println(e.getId());
}
List<Employee> list2 = this.getAllEmployee();
System.out.println("--------------学校总部员工--------------");
for(Employee e : list2) {
System.out.println(e.getId());
}
}
}
public class demeter {
public static void main(String[] args) {
SchoolManagement schoolManagement = new SchoolManagement();
schoolManagement.printAllEmployee(new CollegeManagement());
}
}
package com.tensoflow.principle.demeter.improve1;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
// 学校总部员工类
@Data
class Employee {
private String id;
}
// 学院员工类
@Data
class CollegeEmployee {
private String id;
}
// 管理学院员工的管理类
class CollegeManagement {
public List<CollegeEmployee> getAllEmployee() {
List<CollegeEmployee> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
CollegeEmployee emp = new CollegeEmployee();
emp.setId("学院员工Id = " + i);
list.add(emp);
}
return list;
}
public void printEmployee() {
List<CollegeEmployee> list = this.getAllEmployee();
System.out.println("--------------分公司员工--------------");
for(CollegeEmployee e : list) {
System.out.println(e.getId());
}
}
}
class SchoolManagement {
public List<Employee> getAllEmployee() {
List<Employee> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Employee emp = new Employee();
emp.setId("学校总部员工Id = " + i);
list.add(emp);
}
return list;
}
// 输出学校总部和学院员工信息的方法
void printAllEmployee(CollegeManagement sub) {
// 将输出学院员工方法封装到CollegeManagement中去
sub.printEmployee();
List<Employee> list = this.getAllEmployee();
System.out.println("--------------学校总部员工--------------");
for(Employee e : list) {
System.out.println(e.getId());
}
}
}
public class demeter {
public static void main(String[] args) {
SchoolManagement schoolManagement = new SchoolManagement();
schoolManagement.printAllEmployee(new CollegeManagement());
}
}
接口隔离原则
客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小的接口上。
package com.tensoflow.principle.segregation.problem;
interface Interface1 {
void operation1();
void operation2();
void operation3();
void operation4();
void operation5();
}
class B implements Interface1 {
@Override
public void operation1() {
System.out.println("B 实现了 operation1");
}
@Override
public void operation2() {
System.out.println("B 实现了 operation2");
}
@Override
public void operation3() {
System.out.println("B 实现了 operation3");
}
@Override
public void operation4() {
System.out.println("B 实现了 operation4");
}
@Override
public void operation5() {
System.out.println("B 实现了 operation5");
}
}
class D implements Interface1 {
@Override
public void operation1() {
System.out.println("D 实现了 operation1");
}
@Override
public void operation2() {
System.out.println("D 实现了 operation2");
}
@Override
public void operation3() {
System.out.println("D 实现了 operation3");
}
@Override
public void operation4() {
System.out.println("D 实现了 operation4");
}
@Override
public void operation5() {
System.out.println("D 实现了 operation5");
}
}
// A类通过Interface1接口依赖(使用)B类,只会用到1,2,3个方法
class A {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface1 i) {
i.operation2();
}
public void depend3(Interface1 i) {
i.operation3();
}
}
// C类通过Interface1接口依赖(使用)D类,只会用到1,4,5个方法
class C {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend4(Interface1 i) {
i.operation4();
}
public void depend5(Interface1 i) {
i.operation5();
}
}
/*
问题分析:
B类实现了Interface1接口
A类通过Interface1接口依赖B类
但是接口对于A类来说不是最小接口,因为A类只会使用接口中的1,2,3方法
B类需要实现接口的所有方法。造成了B类实现了根本不需要实现的方法
解决方式:
将接口Interface1拆分为独立的几个接口,A类和C类分别与它们需要的接口建立依赖关系
*/
public class Segregation {
public static void main(String[] args) {
A a = new A();
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
}
}
package com.tensoflow.principle.segregation.improve1;
interface Interface1 {
void operation1();
}
interface Interface2 {
void operation2();
void operation3();
}
interface Interface3 {
void operation4();
void operation5();
}
class B implements Interface1, Interface2 {
@Override
public void operation1() {
System.out.println("B 实现了 operation1");
}
@Override
public void operation2() {
System.out.println("B 实现了 operation2");
}
@Override
public void operation3() {
System.out.println("B 实现了 operation3");
}
}
class D implements Interface1, Interface3 {
@Override
public void operation1() {
System.out.println("D 实现了 operation1");
}
@Override
public void operation4() {
System.out.println("D 实现了 operation4");
}
@Override
public void operation5() {
System.out.println("D 实现了 operation5");
}
}
// A类通过Interface1、Interface2接口依赖(使用)B类,只会用到1,2,3个方法
class A {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend2(Interface2 i) {
i.operation2();
}
public void depend3(Interface2 i) {
i.operation3();
}
}
// C类通过Interface1、Interface3接口依赖(使用)D类,只会用到1,4,5个方法
class C {
public void depend1(Interface1 i) {
i.operation1();
}
public void depend4(Interface3 i) {
i.operation4();
}
public void depend5(Interface3 i) {
i.operation5();
}
}
public class Segregation {
public static void main(String[] args) {
A a = new A();
a.depend1(new B());
a.depend2(new B());
a.depend3(new B());
C c = new C();
c.depend1(new D());
c.depend4(new D());
c.depend5(new D());
}
}
依赖倒转原则
高层模块不应该依赖底层模块,二者都应该依赖其抽象
抽象不应该依赖细节,细节应该依赖抽象
依赖倒转原则的中心思想:面向接口编程
依赖倒转原则的设计理念:相对于细节的多变性,抽象的东西要稳定的多,以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在Java中,抽象指的是接口或抽象类,细节就是具体的实现类。
使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
package com.tensoflow.principle.inversion.problem;
class Email {
public String getInfo() {
return "电子邮件信息: Hello World!";
}
}
class Person {
public void receive(Email email) {
System.out.println(email.getInfo());
}
}
/*
Person有接收邮件消息的功能
问题分析:
如果需要获取的对象是微信、短信等。则需要增加新的类并且Person也要增加相应的接收方法
解决方案:
引入一个抽象的接口IReceiver,表示接收者让Person类与接口发生依赖。
然后让Email、WeiXin等去实现IReceiver接口。
*/
public class Inversion {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
}
}
package com.tensoflow.principle.inversion.improve1;
interface IReceive {
String getInfo();
}
class Email implements IReceive {
@Override
public String getInfo() {
return "电子邮件信息: Hello World!";
}
}
class WeiXin implements IReceive {
@Override
public String getInfo() {
return "微信信息: Hello TenSoFlow!";
}
}
// 依赖接口不要依赖具体类
class Person {
public void receive(IReceive iReceive) {
System.out.println(iReceive.getInfo());
}
}
public class Inversion {
public static void main(String[] args) {
Person person = new Person();
person.receive(new Email());
person.receive(new WeiXin());
}
}
里氏替换原则
在使用继承时,在子类中尽量不要重写父类的方法。在适当的情况下,可以通过聚合、组合、依赖的来解决问题。
package com.tensoflow.principle.liskov.problem;
class A {
// 两数求差
public int func1(int a, int b) {
return a - b;
}
}
// B类继承了A
// 并增加了一个新功能:完成两个数相加然后和9求和
class B extends A {
// B类重写了父类方法,改变了其逻辑
@Override
public int func1(int a, int b) {
return a + b;
}
// 新功能:完成两个数相加然后和9求和
public int func2(int a, int b) {
return func1(a, b) + 9;
}
}
/*
问题分析:
原来运行正常的求差功能发生了错误,原因是B类无语重写了父类方法,造成原有功能出现错误。
在实际编程中常常会重写父类方法完成新功能,这样写起来虽然简单,但是整个集成体系的复用性会比较差。
特别是运行多态比较频繁的时候。
解决方案:
原来的父类和子类都继承一个更通俗的基类,原有的继承关系去掉,采用依赖、聚合、组合等关系代替。
*/
public class Liskov {
public static void main(String[] args) {
A a = new A();
System.out.println("11 - 3 = " + a.func1(11, 3));
System.out.println("-------------------");
B b = new B();
// 这里本意是求出11 - 3的结果但是B已经重写了A中的方法造成结果错误
System.out.println("11 - 3 = " + b.func1(11, 3));
System.out.println("11 + 3 + 9 = " + b.func2(11, 3));
}
}
package com.tensoflow.principle.liskov.improve1;
class Base {
// 把更加基础的方法和成员写到Base类
}
class A extends Base{
// 两数求差
public int func1(int a, int b) {
return a - b;
}
}
class B extends Base {
private A a = new A();
// 保持自己的func1逻辑
public int func1(int a, int b) {
return a + b;
}
// 新功能:完成两个数相加然后和9求和
public int func2(int a, int b) {
return func1(a, b) + 9;
}
// 在func3中使用A的方法
public int func3(int a, int b) {
return this.a.func1(a, b);
}
}
public class Liskov {
public static void main(String[] args) {
A a = new A();
System.out.println("11 - 3 = " + a.func1(11, 3));
System.out.println("-------------------");
B b = new B();
// B类不再继承A类,因此调用者不会再认为func1是减法了
System.out.println("11 + 3 = " + b.func1(11, 3));
System.out.println("11 + 3 + 9 = " + b.func2(11, 3));
System.out.println("11 - 3 = " + b.func3(11, 3));
}
}
合成复用原则
原则是尽量使用合成或聚合的方式,而不是使用继承。
开闭原则
模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。
package com.tensoflow.principle.openClose.problem;
// 绘图类 (使用方)
class GraphicEditor {
public void drawShape(Shape s) {
if (s.m_type == 1) {
drawRectangle(s);
} else if (s.m_type == 2) {
drawCircle(s);
}
}
private void drawRectangle(Shape r) {
System.out.println("矩形");
}
private void drawCircle(Shape r) {
System.out.println("圆形");
}
}
class Shape {
int m_type;
}
class Rectangle extends Shape {
Rectangle() {
super.m_type = 1;
}
}
class Circle extends Shape {
Circle() {
super.m_type = 2;
}
}
/*
问题分析:
违反了开闭原则,如果需要增加一个绘制三角形的方法需要更改绘图类(使用方)的代码
解决方案:
把Shape类做成抽象类,并提供一个抽象的draw方法,打子类去实现即可
*/
public class OpenClose {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
}
}
package com.tensoflow.principle.openClose.improve1;
// 绘图类 (使用方)
class GraphicEditor {
public void drawShape(Shape s) {
s.draw();
}
}
abstract class Shape {
public abstract void draw();
}
class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("矩形");
}
}
class Circle extends Shape {
@Override
public void draw() {
System.out.println("圆形");
}
}
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("三角形");
}
}
public class OpenClose {
public static void main(String[] args) {
GraphicEditor graphicEditor = new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
graphicEditor.drawShape(new Triangle());
}
}
创建型模式
单例模式
采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。JDK中Runtime类就是经典的单例模式。
饿汉式(静态变量) -- 可以使用
package com.tensoflow.designPattern.singleton.way01;
/**
* 饿汉式(静态变量)
*/
class MySingleton {
// 构造器私有化,外部不能通过new关键字创建实例
private MySingleton() {}
// 本地内部创建对象实例
private final static MySingleton instance = new MySingleton();
// 对外提供一个公有的静态方法,返回实例对象
public static MySingleton getInstance() {
return instance;
}
}
public class Singleton {
public static void main(String[] args) {
MySingleton instance = MySingleton.getInstance();
MySingleton instance1 = MySingleton.getInstance();
System.out.println(instance == instance1); // true
}
}
优点:写法简单,在类装载的时候就完成实例化。避免了线程同步问题是线程安全的。
缺点:在类装载的时候就完成实例化,没有达到懒加载的效果,如果从始至终从未使用过这个实例,则会造成内存浪费。
总结:这种单例模式可用,可能会造成内存浪费。
饿汉式(静态代码块) -- 不推荐使用
package com.tensoflow.designPattern.singleton.way02;
/**
* 饿汉式(静态代码块)
*/
class MySingleton {
// 构造器私有化,外部不能通过new关键字创建实例
private MySingleton() {}
// 定义私有属性
private static MySingleton instance;
// 静态代码块中创建对象实例
static {
instance = new MySingleton();
}
// 对外提供一个公有的静态方法,返回实例对象
public static MySingleton getInstance() {
return instance;
}
}
public class Singleton {
public static void main(String[] args) {
MySingleton instance = MySingleton.getInstance();
MySingleton instance1 = MySingleton.getInstance();
System.out.println(instance == instance1); // true
}
}
饿汉式(静态代码块)和饿汉式(静态变量)方式一样,只不过创建实例位置在静态代码块中。
懒汉式(线程不安全) -- 不推荐使用
package com.tensoflow.designPattern.singleton.way03;
/**
* 懒汉式(线程不安全)
*/
class MySingleton {
// 构造器私有化,外部不能通过new关键字创建实例
private MySingleton() {}
// 定义私有属性
private static MySingleton instance;
// 对外提供一个公有的静态方法,返回实例对象
public static MySingleton getInstance() {
if (null == instance) {
instance = new MySingleton();
}
return instance;
}
}
public class Singleton {
public static void main(String[] args) {
MySingleton instance = MySingleton.getInstance();
MySingleton instance1 = MySingleton.getInstance();
System.out.println(instance == instance1); // true
}
}
起到了懒加载的效果,但是只能在单线程下使用。
懒汉式(线程安全-效率低) -- 不推荐使用
package com.tensoflow.designPattern.singleton.way04;
/**
* 懒汉式(线程安全-效率低)
*/
class MySingleton {
// 构造器私有化,外部不能通过new关键字创建实例
private MySingleton() {}
// 定义私有属性
private static MySingleton instance;
// 对外提供一个公有的静态方法,加入synchronized,返回实例对象
public static synchronized MySingleton getInstance() {
if (null == instance) {
instance = new MySingleton();
}
return instance;
}
}
public class Singleton {
public static void main(String[] args) {
MySingleton instance = MySingleton.getInstance();
MySingleton instance1 = MySingleton.getInstance();
System.out.println(instance == instance1); // true
}
}
达到了懒加载的效果,也达到了线程安全,但是效率低。
懒汉式(线程安全-效率高) -- 推荐使用
package com.tensoflow.designPattern.singleton.way05;
/**
* 懒汉式(线程安全-效率高)
*/
class MySingleton {
// 构造器私有化,外部不能通过new关键字创建实例
private MySingleton() {}
// 定义私有属性 volatile可以立即更新到主存
private static volatile MySingleton instance;
// 对外提供一个公有的静态方法,返回实例对象
public static MySingleton getInstance() {
if (null == instance) {
synchronized (MySingleton.class) {
if (null == instance) {
instance = new MySingleton();
}
}
}
return instance;
}
}
public class Singleton {
public static void main(String[] args) {
MySingleton instance = MySingleton.getInstance();
MySingleton instance1 = MySingleton.getInstance();
System.out.println(instance == instance1); // true
}
}
达到了懒加载的效果,也达到了线程安全,并且效率高。
静态内部类 -- 推荐使用
package com.tensoflow.designPattern.singleton.way06;
/**
* 静态内部类
*/
class MySingleton {
// 构造器私有化,外部不能通过new关键字创建实例
private MySingleton() {}
// 静态内部类
private static class SingletonInstance {
private static final MySingleton INSTANCE = new MySingleton();
}
// 对外提供一个公有的静态方法,返回实例对象
public static MySingleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
public class Singleton {
public static void main(String[] args) {
MySingleton instance = MySingleton.getInstance();
MySingleton instance1 = MySingleton.getInstance();
System.out.println(instance == instance1); // true
}
}
线程安全,实现了延迟加载,效率高。
枚举 -- 推荐使用
package com.tensoflow.designPattern.singleton.way07;
/**
* 枚举
*/
enum MySingleton {
INSTANCE;
public void ok() {
System.out.println("ok");
}
}
public class Singleton {
public static void main(String[] args) {
MySingleton instance = MySingleton.INSTANCE;
MySingleton instance1 = MySingleton.INSTANCE;
System.out.println(instance == instance1); // true
instance.ok(); // ok
}
}
线程安全,还能防止反序列化重新创建新的对象。其它所有方法都能通过反射来破坏单例。
简单工厂模式
JDK中的Calendar类就是采用的简单工厂模式。
具体需求
有一个披萨的项目:要便于披萨种类的扩展,也要便于维护
1. 披萨的种类有很多比如GreekPizz、CheesePizz
2. 披萨的制作有prepare、bake、cut、box
3. 完成披萨店订购功能
传统方法
package com.tensoflow.designPattern.factory.simpleFactory.problem;
// 披萨商店类 相当于客户端
public class PizzaStore {
public static void main(String[] args) {
new OrderPizza();
}
}
package com.tensoflow.designPattern.factory.simpleFactory.problem;
import lombok.Data;
// 披萨抽象类
@Data
public abstract class Pizza {
// 披萨名字
protected String name;
// 抽象方法:准备原材料
public abstract void prepare();
// 烘烤
public void bake() {
System.out.println(name + " baking...");
}
// 切割
public void cut() {
System.out.println(name + " cut...");
}
// 打包
public void box() {
System.out.println(name + " box...");
}
}
package com.tensoflow.designPattern.factory.simpleFactory.problem;
// 希腊披萨
public class GreekPizza extends Pizza {
@Override
public void prepare() {
System.out.println("准备希腊披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.simpleFactory.problem;
// 奶酪披萨
public class CheesePizza extends Pizza {
@Override
public void prepare() {
System.out.println("准备奶酪披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.simpleFactory.problem;
import java.util.Scanner;
// 订购披萨类
public class OrderPizza {
public OrderPizza() {
Pizza pizza = null;
String orderType;
do {
orderType = getType();
if ("greek".equals(orderType)) {
pizza = new GreekPizza();
pizza.setName("希腊披萨");
} else if ("cheese".equals(orderType)) {
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
} else {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while(true);
}
// 获取输入
private String getType() {
return new Scanner(System.in).nextLine();
}
}
问题分析:上述代码违反了开闭原则,当我们增加一个披萨种类的时候要修改使用方代码即创建Pizze的OrderPizza类。如果在其它地方也要使用创建Pizza的代码,意味着需要多处修改。
解决方案:把创建Pizza对象封装到一个类中,这样有新的Pizza种类时,只需要修改该类就可。其它有创建Pizza对象的代码就不需要修改了即简单工厂模式。
简单工厂模式
简单工厂模式属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。定义一个创建对象的类,由这个类来封装另一个类实例化对象的行为。在软件开发中,当我们会用到大量的创建某一类或者某批对象时,就会使用工厂模式。
package com.tensoflow.designPattern.factory.simpleFactory.improve1;
// 披萨商店类 相当于客户端
public class PizzaStore {
public static void main(String[] args) {
new OrderPizza();
}
}
package com.tensoflow.designPattern.factory.simpleFactory.problem;
import lombok.Data;
// 披萨抽象类
@Data
public abstract class Pizza {
// 披萨名字
protected String name;
// 抽象方法:准备原材料
public abstract void prepare();
// 烘烤
public void bake() {
System.out.println(name + " baking...");
}
// 切割
public void cut() {
System.out.println(name + " cut...");
}
// 打包
public void box() {
System.out.println(name + " box...");
}
}
package com.tensoflow.designPattern.factory.simpleFactory.problem;
// 希腊披萨
public class GreekPizza extends Pizza {
@Override
public void prepare() {
System.out.println("准备希腊披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.simpleFactory.problem;
// 奶酪披萨
public class CheesePizza extends Pizza {
@Override
public void prepare() {
System.out.println("准备奶酪披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.simpleFactory.improve1;
public class SimpleFactory {
// 根据orderType创建对应Pizza
public static Pizza CreatePizza(String orderType){
Pizza pizza = null;
if ("greek".equals(orderType)) {
pizza = new GreekPizza();
pizza.setName("希腊披萨");
} else if ("cheese".equals(orderType)) {
pizza = new CheesePizza();
pizza.setName("奶酪披萨");
}
return pizza;
}
}
package com.tensoflow.designPattern.factory.simpleFactory.improve1;
import java.util.Scanner;
// 订购披萨类
public class OrderPizza {
// 披萨对象
Pizza pizza;
// 构造器
public OrderPizza() {
String orderType = "";
do {
orderType = getType();
pizza = SimpleFactory.CreatePizza(orderType);
if (null == pizza) {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while(true);
}
// 获取输入
private String getType() {
return new Scanner(System.in).nextLine();
}
}
工厂方法模式
新需求:
客户在点披萨时可以点不同口味的披萨。比如北京的奶酪披萨、北京的胡椒披萨、伦敦的奶酪披萨、伦敦的胡椒披萨。
package com.tensoflow.designPattern.factory.factoryMethod;
import com.tensoflow.designPattern.factory.simpleFactory.improve1.OrderPizza;
// 披萨商店类 相当于客户端
public class PizzaStore {
public static void main(String[] args) {
// 创建北京口味的各种披萨
new BJOrderPizza();
// 创建伦敦口味的各种披萨
new LDOrderPizza();
}
}
package com.tensoflow.designPattern.factory.factoryMethod;
import lombok.Data;
// 披萨抽象类
@Data
public abstract class Pizza {
// 披萨名字
protected String name;
// 抽象方法:准备原材料
public abstract void prepare();
// 烘烤
public void bake() {
System.out.println(name + " baking...");
}
// 切割
public void cut() {
System.out.println(name + " cut...");
}
// 打包
public void box() {
System.out.println(name + " box...");
}
}
package com.tensoflow.designPattern.factory.factoryMethod;
import com.tensoflow.designPattern.factory.simpleFactory.improve1.Pizza;
// 奶酪披萨
public class BJCheesePizza extends Pizza {
@Override
public void prepare() {
setName("北京奶酪披萨");
System.out.println("准备北京奶酪披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.factoryMethod;
import com.tensoflow.designPattern.factory.simpleFactory.improve1.Pizza;
// 希腊披萨
public class BJGreekPizza extends Pizza {
@Override
public void prepare() {
setName("北京希腊披萨");
System.out.println("准备北京希腊披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.factoryMethod;
import com.tensoflow.designPattern.factory.simpleFactory.improve1.Pizza;
// 奶酪披萨
public class LDCheesePizza extends Pizza {
@Override
public void prepare() {
setName("伦敦奶酪披萨");
System.out.println("准备伦敦奶酪披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.factoryMethod;
import com.tensoflow.designPattern.factory.simpleFactory.improve1.Pizza;
// 希腊披萨
public class LDGreekPizza extends Pizza {
@Override
public void prepare() {
setName("伦敦希腊披萨");
System.out.println("准备伦敦希腊披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.factoryMethod;
import com.tensoflow.designPattern.factory.simpleFactory.improve1.Pizza;
import java.util.Scanner;
// 订购披萨类
public abstract class OrderPizza {
// 抽象方法,让各个工厂子类自己实现
abstract Pizza createPizza(String orderType);
// 构造器
public OrderPizza() {
Pizza pizza = null;
String orderType = "";
do {
orderType = getType();
// 抽象方法由工厂子类完成
pizza = createPizza(orderType);
if (null == pizza) {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while(true);
}
// 获取输入
private String getType() {
return new Scanner(System.in).nextLine();
}
}
package com.tensoflow.designPattern.factory.factoryMethod;
import com.tensoflow.designPattern.factory.simpleFactory.improve1.Pizza;
public class LDOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if ("greek".equals(orderType)) {
pizza = new LDGreekPizza();
} else if ("cheese".equals(orderType)) {
pizza = new LDCheesePizza();
}
return pizza;
}
}
package com.tensoflow.designPattern.factory.factoryMethod;
import com.tensoflow.designPattern.factory.simpleFactory.improve1.Pizza;
public class BJOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if ("greek".equals(orderType)) {
pizza = new BJGreekPizza();
} else if ("cheese".equals(orderType)) {
pizza = new BJCheesePizza();
}
return pizza;
}
}
抽象工厂模式
定义一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。从设计层面上看,抽象工厂模式就是对简单工厂模式的改进或者称为进一步的抽象。
package com.tensoflow.designPattern.factory.abstractFactory;
// 披萨商店类 相当于客户端
public class PizzaStore {
public static void main(String[] args) {
new OrderPizza(new BJFactory());
new OrderPizza(new LDFactory());
}
}
package com.tensoflow.designPattern.factory.abstractFactory;
import lombok.Data;
// 披萨抽象类
@Data
public abstract class Pizza {
// 披萨名字
protected String name;
// 抽象方法:准备原材料
public abstract void prepare();
// 烘烤
public void bake() {
System.out.println(name + " baking...");
}
// 切割
public void cut() {
System.out.println(name + " cut...");
}
// 打包
public void box() {
System.out.println(name + " box...");
}
}
package com.tensoflow.designPattern.factory.abstractFactory;
// 奶酪披萨
public class BJCheesePizza extends Pizza {
@Override
public void prepare() {
setName("北京奶酪披萨");
System.out.println("准备北京奶酪披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.abstractFactory;
// 希腊披萨
public class BJGreekPizza extends Pizza {
@Override
public void prepare() {
setName("北京希腊披萨");
System.out.println("准备北京希腊披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.abstractFactory;
// 奶酪披萨
public class LDCheesePizza extends Pizza {
@Override
public void prepare() {
setName("伦敦奶酪披萨");
System.out.println("准备伦敦奶酪披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.abstractFactory;
// 希腊披萨
public class LDGreekPizza extends Pizza {
@Override
public void prepare() {
setName("伦敦希腊披萨");
System.out.println("准备伦敦希腊披萨原材料...");
}
}
package com.tensoflow.designPattern.factory.abstractFactory;
// 抽象工厂模式抽象层
public interface AbstractFactory {
public Pizza createPizza(String orderType);
}
package com.tensoflow.designPattern.factory.abstractFactory;
public class BJFactory implements AbstractFactory {
@Override
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if ("greek".equals(orderType)) {
pizza = new BJCheesePizza();
} else if ("cheese".equals(orderType)) {
pizza = new BJGreekPizza();
}
return pizza;
}
}
package com.tensoflow.designPattern.factory.abstractFactory;
public class LDFactory implements AbstractFactory {
@Override
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if ("greek".equals(orderType)) {
pizza = new LDCheesePizza();
} else if ("cheese".equals(orderType)) {
pizza = new LDGreekPizza();
}
return pizza;
}
}
package com.tensoflow.designPattern.factory.abstractFactory;
import java.util.Scanner;
// 订购披萨类
public class OrderPizza {
public AbstractFactory factory;
// 构造器
public OrderPizza(AbstractFactory factory) {
setFactory(factory);
}
public void setFactory(AbstractFactory factory) {
this.factory = factory;
Pizza pizza = null;
String orderType = "";
do {
orderType = getType();
pizza = factory.createPizza(orderType);
if (null == pizza) {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while(true);
}
// 获取输入
private String getType() {
return new Scanner(System.in).nextLine();
}
}
原型模式
需求:
现在有一只羊。姓名:tom,年龄:1,颜色:白色。请编写程序创建和tom羊属性完全相同的10只羊。
传统方法
package com.tensoflow.designPattern.prototype.problem;
import lombok.Data;
@Data
public class Sheep {
private String name;
private Integer age;
private String color;
public Sheep(String name, Integer age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
}
package com.tensoflow.designPattern.prototype.problem;
public class Client {
public static void main(String[] args) {
Sheep sheep = new Sheep("tom", 1, "白色");
Sheep sheep1 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
System.out.println(sheep);
System.out.println(sheep1);
System.out.println(sheep2);
System.out.println(sheep3);
System.out.println(sheep4);
System.out.println(sheep5);
}
}
优点是比较好理解,简单易操作。但是在创建新对象时,总是需要重新获取原始对象的属性,如果创建的对象比较复杂时,效率较低。
原型模式
原型模式(Prototype)是指:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。Java中Object类是所有类的父类,Object类提供了一个clone()方法。该方法可以将一个Java对象复制一份,但是需要实现clone的java类必须要实现一个接口Cloneable,该接口表示该类能够复制且具有复制的能力。Spring中原型Bean的创建就是原型模式。
应用场景:
- 当你有一个配置类 / 常量类(不可变对象),需要基于它做少量修改生成新对象时,直接克隆后修改比重新new并逐个赋值更高效。
- 需要记录对象在某个时间点的状态(快照),后续操作不影响历史状态。典型如编辑器的撤销、游戏存档、数据审计
- 多线程环境下的对象隔离。多线程共享一个对象时,如果某个线程需要修改对象数据,但又不想影响其他线程的读取,可克隆出独立副本供当前线程操作。
package com.tensoflow.designPattern.prototype.improve1;
import lombok.Data;
@Data
public class Sheep implements Cloneable {
private String name;
private Integer age;
private String color;
public Sheep(String name, Integer age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
'}';
}
// 重写clone方法 浅拷贝
@Override
protected Sheep clone(){
try {
return (Sheep) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException("克隆 Sheep 失败", e);
}
}
}
package com.tensoflow.designPattern.prototype.improve1;
public class Client {
public static void main(String[] args) {
Sheep sheep = new Sheep("tom", 1, "白色");
Sheep sheep1 = sheep.clone();
Sheep sheep2 = sheep.clone();
Sheep sheep3 = sheep.clone();
Sheep sheep4 = sheep.clone();
Sheep sheep5 = sheep.clone();
System.out.println(sheep);
System.out.println(sheep1);
System.out.println(sheep2);
System.out.println(sheep3);
System.out.println(sheep4);
System.out.println(sheep5);
}
}
建造者模式
需求:
1. 需要盖房子:打桩、砌墙、封顶
2. 房子有各种各样的比如普通房、高楼、别墅。各种房子的过程虽然一样,但是要求不同。
3. 请编写编程,完成需求。
传统方法
package com.tensoflow.designPattern.builder.problem;
public class Client {
public static void main(String[] args) {
CommonHouse commonHouse = new CommonHouse();
commonHouse.build();
}
}
package com.tensoflow.designPattern.builder.problem;
public abstract class AbstractHouse {
// 打地基
public abstract void buildBasic();
// 砌墙
public abstract void buildWalls();
// 封顶
public abstract void roofed();
// 建造
public void build() {
buildBasic();
buildWalls();
roofed();
}
}
package com.tensoflow.designPattern.builder.problem;
public class CommonHouse extends AbstractHouse {
@Override
public void buildBasic() {
System.out.println("普通房子打地基...");
}
@Override
public void buildWalls() {
System.out.println("普通房子砌墙...");
}
@Override
public void roofed() {
System.out.println("普通房子封顶...");
}
}
优点是比较好理解,简单易操作。但是设计的程序结构过于简单,没有设计缓存层对象,程序的扩展和维护性不好。这种设计把产品和创建产品的过程封装在一起,耦合性增强了。
建造者模式
建造者模式(Builder Pattern)又叫生成器模式,是一种对象构建模式。可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现的对象。允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。JDK中的StringBuilder类就是采用的建造者模式。
建造者模式的四个角色:
Product(产品角色):一个具体的产品对象
Builder(抽象建造者):创建一个Product对象的各个部件指定的接口或者抽象类
ConcreteBuilder(具体建造者):实现接口,构建和装配各个部件
Director(指挥者):构建一个使用Builder接口的对象。主要用于创建一个复杂的对象。能隔离客户与对象的生产过程,还负责控制产品对象的生产过程。
package com.tensoflow.designPattern.builder.improve1;
public class Client {
public static void main(String[] args) {
HouseDirector houseDirector = new HouseDirector(new HighBuilder());
House house = houseDirector.constructHouse();
houseDirector = new HouseDirector(new CommonBuilder());
House house1 = houseDirector.constructHouse();
}
}
package com.tensoflow.designPattern.builder.improve1;
import lombok.Data;
// 产品 --> Product
@Data
public class House {
private String baise;
private String wall;
private String roofed;
}
package com.tensoflow.designPattern.builder.improve1;
// Builder --> 抽象的建造者
public abstract class HouseBuilder {
private House house = new House();
// 打地基
public abstract void buildBasic();
// 砌墙
public abstract void buildWalls();
// 封顶
public abstract void roofed();
// 建造
public House build() {
return house;
}
}
package com.tensoflow.designPattern.builder.improve1;
// 具体建造者 --> ConcreteBuilder
public class HighBuilder extends HouseBuilder {
@Override
public void buildBasic() {
System.out.println("高楼打地基20m...");
}
@Override
public void buildWalls() {
System.out.println("高楼砌墙20cm...");
}
@Override
public void roofed() {
System.out.println("高楼封顶...");
}
}
package com.tensoflow.designPattern.builder.improve1;
// 具体建造者 --> ConcreteBuilder
public class CommonBuilder extends HouseBuilder{
@Override
public void buildBasic() {
System.out.println("普通房子打地基5m...");
}
@Override
public void buildWalls() {
System.out.println("普通房子砌墙10cm...");
}
@Override
public void roofed() {
System.out.println("普通房子封顶...");
}
}
package com.tensoflow.designPattern.builder.improve1;
import lombok.Data;
// 指挥者 --> Director
@Data
public class HouseDirector {
HouseBuilder houseBuilder = null;
public HouseDirector(HouseBuilder houseBuilder){
this.houseBuilder = houseBuilder;
}
// 具体建房步骤
public House constructHouse() {
houseBuilder.buildBasic();
houseBuilder.buildWalls();
houseBuilder.roofed();
return houseBuilder.build();
}
}
适配器模式
适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示。主要目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。分为类适配器模式、对象适配器模式、接口适配器模式。SpringMVC框架中的HandlerAdapter就使用了适配器模式。
类适配器模式
package com.tensoflow.designPattern.adapter.classAdapter;
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter());
}
}
package com.tensoflow.designPattern.adapter.classAdapter;
public class Voltage220V {
// 输出220V电压
public int output220V() {
int src = 220;
System.out.println("电压=" + src + "v");
return src;
}
}
package com.tensoflow.designPattern.adapter.classAdapter;
public interface IVoltage5V {
public int output5V();
}
package com.tensoflow.designPattern.adapter.classAdapter;
// 适配器类
public class VoltageAdapter extends Voltage220V implements IVoltage5V {
@Override
public int output5V() {
int srcV = output220V();
int dstV = srcV / 44;
return dstV;
}
}
package com.tensoflow.designPattern.adapter.classAdapter;
public class Phone {
public void charging(IVoltage5V iVoltage5V) {
if (iVoltage5V.output5V() == 5) {
System.out.println("电压为5V可以充电...");
} else {
System.out.println("电压大于5V无法充电...");
}
}
}
类适配器模式
package com.tensoflow.designPattern.adapter.objectAdapter;
public class Client {
public static void main(String[] args) {
Phone phone = new Phone();
phone.charging(new VoltageAdapter(new Voltage220V()));
}
}
package com.tensoflow.designPattern.adapter.classAdapter;
public class Voltage220V {
// 输出220V电压
public int output220V() {
int src = 220;
System.out.println("电压=" + src + "v");
return src;
}
}
package com.tensoflow.designPattern.adapter.classAdapter;
public interface IVoltage5V {
public int output5V();
}
package com.tensoflow.designPattern.adapter.objectAdapter;
// 适配器类
public class VoltageAdapter implements IVoltage5V {
private Voltage220V voltage220V;
public VoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int output5V() {
int dstV = 0;
if (null != voltage220V) {
int srcV = voltage220V.output220V();
dstV = srcV / 44;
}
return dstV;
}
}
package com.tensoflow.designPattern.adapter.objectAdapter;
public class Phone {
public void charging(IVoltage5V iVoltage5V) {
if (iVoltage5V.output5V() == 5) {
System.out.println("电压为5V可以充电...");
} else {
System.out.println("电压不正确无法充电...");
}
}
}
接口适配器模式
当不需要全部实现接口提供的方法时,可先设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可有选择地覆盖父类的某些方法来实现需求。适用于一个接口不想使用其所有方法的情况。
package com.tensoflow.designPattern.adapter.interfaceAdapter;
public class Client {
public static void main(String[] args) {
AbstractAdapter adapter = new AbstractAdapter() {
// 只需要去重写我们需要使用的方法
@Override
public void method1() {
System.out.println("我只想使用method1方法");
}
};
adapter.method1();
}
}
package com.tensoflow.designPattern.adapter.interfaceAdapter;
public interface IInterface {
public void method1();
public void method2();
public void method3();
public void method4();
}
package com.tensoflow.designPattern.adapter.interfaceAdapter;
public abstract class AbstractAdapter implements IInterface {
public void method1() {}
public void method2() {}
public void method3() {}
public void method4() {}
}
结构型模式
桥接模式
桥接模式(Bridge模式)是指:将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。JDBC中的Driver接口就使用了桥接模式。
package com.tensoflow.designPattern.birdge.improve1;
public class Client {
public static void main(String[] args) {
Phone xiaoMiPhone = new FoldedPhone(new XiaoMi());
xiaoMiPhone.open();
xiaoMiPhone.close();
xiaoMiPhone.call();
System.out.println("========================");
Phone vivoPhone = new UpRightPhone(new Vivo());
vivoPhone.open();
vivoPhone.close();
vivoPhone.call();
}
}
package com.tensoflow.designPattern.birdge.improve1;
public interface Brand {
void open();
void close();
void call();
}
package com.tensoflow.designPattern.birdge.improve1;
public class Vivo implements Brand{
@Override
public void open() {
System.out.println("Vivo手机开机");
}
@Override
public void close() {
System.out.println("Vivo手机关机");
}
@Override
public void call() {
System.out.println("Vivo手机打电话");
}
}
package com.tensoflow.designPattern.birdge.improve1;
public class XiaoMi implements Brand{
@Override
public void open() {
System.out.println("小米手机开机");
}
@Override
public void close() {
System.out.println("小米手机关机");
}
@Override
public void call() {
System.out.println("小米手机打电话");
}
}
package com.tensoflow.designPattern.birdge.improve1;
public abstract class Phone {
// 聚合品牌
private Brand brand;
public Phone(Brand brand) {
this.brand = brand;
}
protected void open() {
this.brand.open();
}
protected void close() {
this.brand.close();
}
protected void call() {
this.brand.call();
}
}
package com.tensoflow.designPattern.birdge.improve1;
public class FoldedPhone extends Phone {
public FoldedPhone(Brand brand) {
super(brand);
}
public void open() {
super.open();
System.out.println("折叠样式手机");
}
public void close() {
super.close();
System.out.println("折叠样式手机");
}
public void call() {
super.call();
System.out.println("折叠样式手机");
}
}
package com.tensoflow.designPattern.birdge.improve1;
public class UpRightPhone extends Phone{
public UpRightPhone(Brand brand) {
super(brand);
}
public void open() {
super.open();
System.out.println("直立样式手机");
}
public void close() {
super.close();
System.out.println("直立样式手机");
}
public void call() {
super.call();
System.out.println("直立样式手机");
}
}
行为型模式
