任何人类产品都是可以拆分的,而后进行重新组合,所以这样设计中被称为合成设计模式。
定义出一种可以描述电脑组成的类,在这样状态下就应该进行拆分为显示器与主机。而主机可以进一步拆分成主板、鼠标和键盘。主板又可以拆分成内存、cpu、显卡、键盘。
再比如:C盘中有一个文件夹jdk,文件夹jdk中存在两个文件jdk1.txt与jdk2.txt。这两个txt文件共同组成了jdk这个文件夹。这个文件夹再与其他同路径文件组成C盘。反过来就可以将C盘拆分成层层文件。
像这种把需要设计的东西经过层层拆分,拆分成不同的组成部件,在需要使用的时候按照规则经过调用拼装,形成需要的产品整体。
例子:
class 电脑{ //1,电脑由多个显示器和一个主机组成
private 显示器 对象数组[];
private 主机 主机;
}
class 显示器{ } //1.1
class 主机{ //1.2 ,主机由主板、鼠标、键盘组成
private 主板 对象;
private 鼠标 对象;
private 键盘 对象;
}
class 主板{ //1.2.1,主板由内存、cpu、显卡、硬盘组成
private 内存 对象数组[];
private cpu 对象数组[];
private 显卡 对象;
private 硬盘 对象数组[];
}
class 键盘{ } //1.2.2
class 鼠标{ } //1.2.3
class 内存{ } //1.2.1.1
class CPU{ } //1/2.1.2
class 显卡{ } //1.2.1.3
class 硬盘{ } //1.2.1.4
public class Array{
public static void main (String args[]){
}
}
假设有三类事物:
·机器类:不休息、补充能量、工作;
·人类:休息、吃饭、努力工作;
·猪类:睡觉、吃食、不工作;
这个时候需要一个公共的模板来实现,定义一个抽象类模板
图片来源(阿里云视频课)
其中行为类为这三个类的公共模板,定义行为类为抽象类,机器人、人、猪分别继承这个抽象行为类,通过方法覆写来实现各自的行为习惯。这个行为类就为其他三个子类的父类模板。这种设计模式叫做模板设计模式。
abstract class Action{ //抽象类
public static final int eating=1; //定义全局常量指令,1表示吃
public static final int sleeping=5;//5代表休息
public static final int working=10;//10表示工作
public void command (int code){ //定义方法,进行指令选择
switch(code){
case eating : {
this.eating();
break;
}
case sleeping : {
this.sleeping();
break;
}
case working : {
this.working();
break;
}
case sleeping +eating+working: {
this.sleeping();
this.eating();
this.working();
break;
}
}
}
public abstract void eating(); //抽象方法
public abstract void sleeping();
public abstract void working();
}
class Robot extends Action{//继承
public void eating(){//覆写方法
System.out.println("补充能量");
}
public void sleeping(){
}
public void working(){
System.out.println("机器工作");
}
}
class Person extends Action{//继承
public void eating(){//覆写方法
System.out.println("人吃饭");
}
public void sleeping(){
System.out.println("人休息");
}
public void working(){
System.out.println("人工作");
}
}
class Pig extends Action{//继承
public void eating(){
System.out.println("猪吃食");
}
public void sleeping(){
System.out.println("猪睡觉");
}
public void working(){
}
}
public class App2 {
public static void main(String[] args){
Action ro=new Robot();//向上转型
Action pe=new Person();
Action pi=new Pig();
System.out.println("----------机器行为----------");
pe.command(Action.sleeping+Action.working+Action.eating);
System.out.println("----------人类行为----------");
pe.command(Action.sleeping+Action.working+Action.eating);
System.out.println("----------猪的行为----------");
pi.command(Action.sleeping+Action.working+Action.eating);
}
}
输出结果:
----------机器行为----------
补充能量
机器工作
----------人类行为----------
人休息
人吃饭
人工作
----------猪的行为----------
猪睡觉
猪吃食
抽象类的好处是对子类方法进行统一管理,自身提供一些普通方法并且这些普通方法可以调用抽象方法,(这些抽象方法必须为子类覆写)
工厂设计模式提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。 由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建对象的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。
例子: 您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
对于接口而言,必须要有子类,并且子类可以通过对象向上转型来获取接口的实例化对象。对象实例化过程存在设计问题。
例子:观察程序
interface IFood{//定义接口标准
public void eat();
}
class Rice implements IFood{
public void eat(){
System.out.println("吃米饭");
}
}
public class Jiekou {
public static void main(String[] args)
{
IFood a=new Rice();
a.eat(); //吃米饭
}
}
此时如果添加一种功能喝饮料,就要修改主类(客户端)中关键字new后面的实例化对象类名,此时就出现了耦合问题,而造成耦合最直接的原因是“关键字new”。而JVM的核心原理是利用java虚拟机运行Java程序,操作系统与程序之间并不直接关联,由JVM来匹配。良好的设计应该避免耦合。(高内聚,低耦合)
例子:修改以上例子
interface IFood{//定义接口标准
public void eat();
}
class Rice implements IFood{
public void eat(){
System.out.println("吃米饭");
}
}
class Drink implements IFood{
public void eat(){
System.out.println("喝饮料");
}
}
class Factory{
public static IFood get(String className){
if ("rice".equals(className)){
return new Rice();
}else if ("drink".equals(className)){
return new Drink();
}else{
return null;
}
}
}
public class Jiekou {
public static void main(String[] args)
{
IFood food=Factory.get(args [0]);
food.eat();
}
}
输出结果:
F:\Java学习\java>java Jiekou rice
吃米饭
F:\Java学习\java>java Jiekou drink
喝饮料
在本程序中,客户端程序类与IFood接口的子类没有任何关联,所有的关联都是通过Factor类完成的,在程序运行时候通过初始化参数进行要使用的子类定义。
如果在日后进行子类扩充的时候,只需要修改factory类的程序类即可。
代理设计模式功能是帮助用户将所有的开发注意力只集中在核心业务功能的处理上。例如:肚子饿了,如何可以吃的东西。
代理设计模式主要特点是一个接口提供两个子类,其中一个子类是真实业务操作类,另一个子类是代理业务操作类。没有代理业务真实业务无法操作。
例子:实现代理设计
interface IEat{//定义接口标准
public void getEat();
}
class Person implements IEat{ //吃的主体人
public void getEat(){
System.out.println("得到食物开始吃东西");
}
}
class EatSever implements IEat{//为吃提供准备服务
private IEat eating;//为吃服务
public EatSever (IEat eating){
this.eating=eating;
}
public void getEat(){
this.prepare();
this.make();
this.eating.getEat();
this.clear();
}
public void prepare(){//准备过程
System.out.println("第一步:购买食材");
}
public void make(){
System.out.println("第二步:加工食材");
}
public void clear(){
System.out.println("第三步:收拾碗筷");
}
}
public class Jiekou {
public static void main(String[] args) {
IEat a=new EatSever(new Person());
a.getEat();
}
}
输出结果:
第一步:购买食材
第二步:加工食材
得到食物开始吃东西
吃完东西付钱
第三步:收拾碗筷
单例设计模式主要是一种控制实例化对象产生个数的设计操作。
1·假设有一个程序类需要实例化多个对象,定义如下:
package b.b.b;
class MessageImpl{
public void send(){
System.out.println("江湖再见");
}
}
public class Message{
public static void main(String args []){
MessageImpl a=new MessageImpl();
MessageImpl b=new MessageImpl();
MessageImpl c=new MessageImpl();
a.send();
b.send();
c.send();
}
}
2·若要求只能有一个实例化对象,使用private访问权限,不能在类外部访问,可以在类本身调用。修改如下:
package b.b.b;
class MessageImpl{
private MessageImpl a=new MessageImpl();
private MessageImpl(){}//构造方法私有化
public void send(){
System.out.println("江湖再见");
}
}
public class Message{
public static void main(String args []){
MessageImpl b=null;//声明对象
}
}
3·此时MessageImpl类内部a属于一个普通属性,普通属性是产生实例化对象之后调用的,但是此时无法实例化对象,这个属性也就不能访问。就应该考虑如何不经过实例化对象获取此属性,只有static属性可以使用。
package b.b.b;
class MessageImpl{
static MessageImpl a=new MessageImpl();
private MessageImpl(){}//构造方法私有化
public void send(){
System.out.println("江湖再见");
}
}
public class Message{
public static void main(String args []){
MessageImpl a=null;//声明对象
a = MessageImpl.a;
a.send();//江湖再见
}
}
4·类中属性应该封装之后使用,所以类中属性a应该被封装。
package b.b.b;
class MessageImpl{
private static MessageImpl a=new MessageImpl();
private MessageImpl(){}//构造方法私有化
public static MessageImpl getA(){
return a;
}
public void send(){
System.out.println("江湖再见");
}
}
public class Message{
public static void main(String args []){
MessageImpl a=null;//声明对象
a = MessageImpl.getA();
a.send();//江湖再见
}
}
5·整个代码要求只有一个实例化对象,虽然提供static实例化对象,但是这个对象依然可以被重新实例化——{a=new MessageImpl()}。所以需要保证MessageImpl类内部无法再次实例化,应该使用final定义。
由此可以得到单例设计模式中的饿汉式实现:
package b.b.b;
class MessageImpl{
private static final MessageImpl A=new MessageImpl();
private MessageImpl(){}//构造方法私有化
public static MessageImpl getA(){
return A;
}
public void send(){
System.out.println("江湖再见");
}
}
public class Message{
public static void main(String args []){
MessageImpl a=null;//声明对象
a = MessageImpl.getA();
a.send();//江湖再见
}
单例设计模式: 假如一个实例化对象在程序运行中一直存在并且不会发生改变,此时设置唯一实例化对象,不管谁调用都无需重新实例化对象,实现实例化对象共享,节约了空间。(如在电脑操作过程中,从任何位置删除文件或打开回收站,都是同一个回收站,电脑各盘共享回收站)
对于单例设计模式分为两种:
1·懒汉式:在第一次使用时候进行实例化对象处理;
2·饿汉式:在系统加载类的时候会自动加载类的实例化对象。
将上述饿汉式改为懒汉式:
package b.b.b;
class MessageImpl{
private static MessageImpl a;
private MessageImpl(){}//构造方法私有化
public static MessageImpl getA(){
if (a==null){ //第一次声明
a=new MessageImpl();//实例化对象
}
return a;
}
public void send(){
System.out.println("江湖再见");
}
}
public class Message{
public static void main(String args []){
MessageImpl a=null;//声明对象
a = MessageImpl.getA();
a.send();//江湖再见
}
}
构造方法私有以后一定要提供static方法返回对象。
多例与单例设计本质相同,内部提供static方法返回实例化对象。
如果要定义一个描述性别的对象:男或女;
class Sex{
private static final Sex M=new Sex("男");
private static final Sex W=new Sex("女");
private String sex;
private Sex(String sex) {
this.sex=sex;
}
public static Sex getSex(String sex) {
switch(sex) {
case "男":return M;
case "女":return W;
default:return null;
}
}
public String getInfo() {
return this.sex;
}
}
public class Java{
public static void main(String args[]) {
Sex a=Sex.getSex("男");
System.out.println(a.getInfo());
}
}
定义一个三原色对象:红黄蓝。
package a.a.a;
class Color{
private static final Color a=new Color("红");
private static final Color b=new Color("黄");
private static final Color c=new Color("蓝");
private String name;
private Color(String name){//构造方法私有化
this.name=name;
}
public static Color getColor(String color){
switch(color){
case "red":return a;
case "yellow":return b;
case "blue":return c;
default:return null;
}
}
public String toString(){
return this.color;
}
}
public class Java {
public static void main(String[] args) {
Color x=Color.getColor("yellow");
System.out.println(x.toString());
}
}